diff --git a/rainbow/Telpp/DrawDragRect.cpp b/rainbow/Telpp/DrawDragRect.cpp index 6bd413089..b9972c0dc 100644 --- a/rainbow/Telpp/DrawDragRect.cpp +++ b/rainbow/Telpp/DrawDragRect.cpp @@ -1,5 +1,7 @@ #include "Local.h" +#ifdef GUI_TELPP + NAMESPACE_UPP struct DrawDragRectInfo { @@ -92,3 +94,5 @@ void FinishDragRect(Ctrl& q) } END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/Telpp/TelDraw.cpp b/rainbow/Telpp/TelDraw.cpp index 1d8454c8f..71ad63ce2 100644 --- a/rainbow/Telpp/TelDraw.cpp +++ b/rainbow/Telpp/TelDraw.cpp @@ -1,4 +1,6 @@ -#include "Telpp.h" +#include + +#ifdef GUI_TELPP NAMESPACE_UPP @@ -99,3 +101,5 @@ void SystemDraw::PutRect(const Rect& r, Color color) } END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/Telpp/Telpp.html b/rainbow/Telpp/Telpp.html index a6369c1b7..7601b3bd4 100644 --- a/rainbow/Telpp/Telpp.html +++ b/rainbow/Telpp/Telpp.html @@ -223,6 +223,7 @@ document.onkeydown = function(event) { event_queue += "K " + event.keyCode + " " + event.which + key_flags(event); Ping(); + Ping(); } document.onkeypress = function(event) diff --git a/rainbow/Turtle/After.h b/rainbow/Turtle/After.h new file mode 100644 index 000000000..f164f44c4 --- /dev/null +++ b/rainbow/Turtle/After.h @@ -0,0 +1,46 @@ +class ViewDraw : public SystemDraw { +public: + ViewDraw(Ctrl *ctrl); + ~ViewDraw(); +}; + + +/* +class ViewDraw : public SystemDraw { + Vector dummy; +public: + ViewDraw(Ctrl *) : SystemDraw(Ctrl::framebuffer, dummy) { dummy.Add(Rect(10, 10, 100, 100)); } +}; +*/ +class DHCtrl : Ctrl {}; + +#ifdef PLATFORM_WIN32 +#define GUI_APP_MAIN \ +void GuiMainFn_(); \ +\ +extern "C" int main(int argc, const char **argv, const char **envptr) { \ + UPP::AppInitEnvironment__(); \ + UPP::Ctrl::InitTelpp(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() + +#endif + +#ifdef PLATFORM_POSIX +#define GUI_APP_MAIN \ +void GuiMainFn_(); \ +\ +extern "C" int main(int argc, const char **argv, const char **envptr) { \ + UPP::AppInit__(argc, argv, envptr); \ + UPP::Ctrl::InitTelpp(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() +#endif diff --git a/rainbow/Turtle/ChSysInit.cpp b/rainbow/Turtle/ChSysInit.cpp new file mode 100644 index 000000000..def0a57e1 --- /dev/null +++ b/rainbow/Turtle/ChSysInit.cpp @@ -0,0 +1,21 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +void ChSysInit() +{ + CtrlImg::Reset(); + CtrlsImg::Reset(); + ChReset(); +} + +void ChHostSkin() +{ + ChSysInit(); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Clip.cpp b/rainbow/Turtle/Clip.cpp new file mode 100644 index 000000000..fa19cee0e --- /dev/null +++ b/rainbow/Turtle/Clip.cpp @@ -0,0 +1,238 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +static VectorMap fbClipboard; + +void ClearClipboard() +{ + GuiLock __; + fbClipboard.Clear(); +} + +void AppendClipboard(const char *format, const Value& data, String (*render)(const Value&)) +{ + GuiLock __; + ClipData& cd = fbClipboard.GetAdd(format); + cd.data = data; + cd.render = render; +} + +static String sRawRender(const Value& v) +{ + return v; +} + +void AppendClipboard(const char *format, const String& data) +{ + GuiLock __; + AppendClipboard(format, data, sRawRender); +} + +void AppendClipboard(const char *format, const byte *data, int length) +{ + GuiLock __; + AppendClipboard(format, String(data, length)); +} + +String ReadClipboard(const char *format) +{ + GuiLock __; + int q = fbClipboard.Find(format); + return q >= 0 ? (*fbClipboard[q].render)(fbClipboard[q].data) : String(); +} + +void AppendClipboardText(const String& s) +{ + AppendClipboard("text", ToSystemCharset(s)); +} + +void AppendClipboardUnicodeText(const WString& s) +{ + AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); +} + +const char *ClipFmtsText() +{ + return "wtext;text"; +} + +String GetString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString(); + } + if(clip.IsAvailable("text")) + return ~clip; + return Null; +} + +WString GetWString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)); + } + if(clip.IsAvailable("text")) + return (~clip).ToWString(); + return Null; +} + + +bool AcceptText(PasteClip& clip) +{ + return clip.Accept(ClipFmtsText()); +} + +static String sText(const Value& data) +{ + return data; +} + +static String sWText(const Value& data) +{ + return Unicode__(WString(data)); +} + +void Append(VectorMap& data, const String& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +void Append(VectorMap& data, const WString& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +String GetTextClip(const WString& text, const String& fmt) +{ + if(fmt == "text") + return text.ToString(); + if(fmt == "wtext") + return Unicode__(text); + return Null; +} + +String GetTextClip(const String& text, const String& fmt) +{ + if(fmt == "text") + return text; + if(fmt == "wtext") + return Unicode__(text.ToWString()); + return Null; +} + +String ReadClipboardText() +{ + String w = ReadClipboard("text"); + return w.GetCount() ? w : ReadClipboardUnicodeText().ToString(); +} + +WString ReadClipboardUnicodeText() +{ + String w = ReadClipboard("wtext"); + if(w.GetCount()) + return WString((const wchar *)~w, w.GetLength() / 2); + return ReadClipboard("text").ToWString(); +} + +bool IsClipboardAvailable(const char *id) +{ + return fbClipboard.Find(id) >= 0; +} + +bool IsClipboardAvailableText() +{ + return IsClipboardAvailable("text") || IsClipboardAvailable("wtext"); +} + +const char *ClipFmtsImage() +{ + static const char *q; + ONCELOCK { + static String s = "dib;" + ClipFmt(); + q = s; + } + return q; +} + +bool AcceptImage(PasteClip& clip) +{ + GuiLock __; + return clip.Accept(ClipFmtsImage()); +} + +Image GetImage(PasteClip& clip) +{ + GuiLock __; + Image m; + if(Accept(clip)) { + LoadFromString(m, ~clip); + if(!m.IsEmpty()) + return m; + } + return Null; +} + +Image ReadClipboardImage() +{ + GuiLock __; + PasteClip d = Ctrl::Clipboard(); + return GetImage(d); +} + +String sImage(const Value& image) +{ + Image img = image; + return StoreAsString(const_cast(img)); +} + +String GetImageClip(const Image& img, const String& fmt) +{ + GuiLock __; + if(img.IsEmpty()) return Null; + if(fmt == ClipFmt()) + return sImage(img); + return Null; +} + +void AppendClipboardImage(const Image& img) +{ + GuiLock __; + if(img.IsEmpty()) return; + AppendClipboard(ClipFmt(), img, sImage); +} + +bool AcceptFiles(PasteClip& clip) +{ + if(clip.Accept("files")) { + clip.SetAction(DND_COPY); + return true; + } + return false; +} + +bool IsAvailableFiles(PasteClip& clip) +{ + return clip.IsAvailable("files"); +} + +Vector GetFiles(PasteClip& clip) +{ + GuiLock __; + Vector f; + return f; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Ctrl.cpp b/rainbow/Turtle/Ctrl.cpp new file mode 100644 index 000000000..d1d930c75 --- /dev/null +++ b/rainbow/Turtle/Ctrl.cpp @@ -0,0 +1,81 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +#define LLOG(x) // DLOG(x) + +NAMESPACE_UPP + +void Ctrl::GuiPlatformConstruct() +{ +} + +void Ctrl::GuiPlatformRemove() +{ +} + +void Ctrl::GuiPlatformGetTopRect(Rect& r) const +{ +} + +bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r) +{ + return false; +} + +bool Ctrl::GuiPlatformSetFullRefreshSpecial() +{ + return false; +} + +void Ctrl::PaintCaret(SystemDraw& w) +{ +} + +String GuiPlatformGetKeyDesc(dword key) +{ + return Null; +} + +void Ctrl::GuiPlatformSelection(PasteClip&) +{ +} + +void GuiPlatformAdjustDragImage(ImageBuffer&) +{ +} + +bool GuiPlatformHasSizeGrip() +{ + return true; +} + +void GuiPlatformGripResize(TopWindow *q) +{ + q->GripResize(); +} + +Color GuiPlatformGetScreenPixel(int x, int y) +{ + return Null; +} + +void GuiPlatformAfterMenuPopUp() +{ +} + +String Ctrl::Name() const { + GuiLock __; +#ifdef CPU_64 + String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this); +#else + String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this); +#endif + if(IsChild()) + s << "(parent " << String(typeid(*parent).name()) << ")"; + return s; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Ctrl.h b/rainbow/Turtle/Ctrl.h new file mode 100644 index 000000000..9d667ed32 --- /dev/null +++ b/rainbow/Turtle/Ctrl.h @@ -0,0 +1,84 @@ +//$ class Ctrl { +private: + static Ptr desktop; + static Vector topctrl; + static bool invalid; + + static Point fbCursorPos; + static Image fbCursorImage; + static bool sdlMouseIsIn; + + static Rect fbCaretRect; + static int fbCaretTm; + + static bool fbEndSession; + static int64 fbEventLoop; + static int64 fbEndSessionLoop; + + static void CursorSync(); + + int FindTopCtrl() const; + static Rect GetClipBound(const Vector& inv, const Rect& r); + static void DoPaint(); + static void SyncTopWindows(); + +// static void AddInvalid(const Rect& rect); + + void DestroyWnd(); + + void NewTop() { top = new Top; top->owner_window = NULL; } + void PutForeground(); + static void MouseEventFB(Ptr t, int event, Point p, int zdelta); + + static void DrawLine(const Vector& clip, int x, int y, int cx, int cy, bool horz, + const byte *pattern, int animation); + static void DragRectDraw0(const Vector& clip, const Rect& rect, int n, + const byte *pattern, int animation); + + static void ReadKeyMods(CParser& p); + static void DoMouseButton(int event, CParser& p); + + static void DoMouseFB(int event, Point p, int zdelta, CParser& cp); + + static void Reply(); + + friend struct PaintProxy__; + friend class TopWindowFrame; + friend class SystemDraw; + friend struct DnDLoop; + + void SetOpen(bool b) { isopen = b; } + +protected: + static int PaintLock; + +public: + static bool DoKeyFB(dword key, int cnt); + + static void InitTelpp(); + static void Exit(); + + static void EndSession(); + + static void SetDesktop(Ctrl& q); + static Ctrl *GetDesktop() { return desktop; } + static void SetDesktopSize(Size sz); + + static void Invalidate() { invalid = true; } + + void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, int type, int animation); + + static Ctrl *FindMouseTopCtrl(); + + static void PaintScene(SystemDraw& draw); + static void PaintCaretCursor(SystemDraw& draw); + + static bool SystemCursor; + + enum { DRAWDRAGRECT_SCREEN = 0x8000 }; + + _TODO_ + static bool ProcessEventQueue(const String& event_queue); + +//$ }; diff --git a/rainbow/Turtle/Cursor.cpp b/rainbow/Turtle/Cursor.cpp new file mode 100644 index 000000000..fe730190e --- /dev/null +++ b/rainbow/Turtle/Cursor.cpp @@ -0,0 +1,22 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) LOG(x) +#define LDUMP(x) //DDUMP(x) + +void Ctrl::SetMouseCursor(const Image& image) +{ + GuiLock __; + if(image.GetSerialId() != fbCursorImage.GetSerialId()) { + fbCursorImage = image; + fbCursorPos = Null; + _TODO_ + } +} + +END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/Turtle/DnD.cpp b/rainbow/Turtle/DnD.cpp new file mode 100644 index 000000000..216323ee0 --- /dev/null +++ b/rainbow/Turtle/DnD.cpp @@ -0,0 +1,150 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) // DLOG(x) + +// -------------------------------------------------------------------------------------------- + +Ptr sDnDSource; + +Ctrl * Ctrl::GetDragAndDropSource() +{ + return sDnDSource; +} + +struct DnDLoop : LocalLoop { + const VectorMap *data; + Vector fmts; + + Image move, copy, reject; + Ptr target; + int action; + byte actions; + + void Sync(); + String GetData(const String& f); + void DnD(bool paste); + + virtual void LeftUp(Point, dword); + virtual bool Key(dword, int); + virtual void MouseMove(Point p, dword); + virtual Image CursorImage(Point, dword); +}; + +Ptr dndloop; + +bool PasteClip::IsAvailable(const char *fmt) const +{ + GuiLock __; + return dnd ? dndloop && FindIndex(dndloop->fmts, fmt) >= 0 + : IsClipboardAvailable(fmt); +} + +String DnDLoop::GetData(const String& f) +{ + GuiLock __; + int i = data->Find(f); + String d; + if(i >= 0) + d = (*data)[i].Render(); + else + if(sDnDSource) + d = sDnDSource->GetDropData(f); + return d; +} + +String PasteClip::Get(const char *fmt) const +{ + return dnd ? dndloop ? dndloop->GetData(fmt) : String() : ReadClipboard(fmt); +} + +void PasteClip::GuiPlatformConstruct() +{ + dnd = false; +} + +void DnDLoop::DnD(bool paste) +{ + PasteClip d; + d.paste = paste; + d.accepted = false; + d.allowed = (byte)actions; + d.action = GetCtrl() ? DND_COPY : DND_MOVE; + d.dnd = true; + if(target) + target->DnD(GetMousePos(), d); + action = d.IsAccepted() ? d.GetAction() : DND_NONE; +} + +void DnDLoop::Sync() +{ + GuiLock __; + Ptr t = FindMouseTopCtrl(); + if(t != target) + if(target) + target->DnDLeave(); + target = t; + DnD(false); +} + +void DnDLoop::LeftUp(Point, dword) +{ + GuiLock __; + LLOG("DnDLoop::LeftUp"); + DnD(true); + EndLoop(); +} + +void DnDLoop::MouseMove(Point p, dword) +{ + GuiLock __; + LLOG("DnDLoop::MouseMove"); + Sync(); +} + +bool DnDLoop::Key(dword, int) +{ + GuiLock __; + LLOG("DnDLoop::Key"); + Sync(); + return false; +} + +Image DnDLoop::CursorImage(Point, dword) +{ + GuiLock __; + return action == DND_MOVE ? move : action == DND_COPY ? copy : reject; +} + +int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, + const VectorMap& data) +{ + GuiLock __; + DnDLoop d; + d.actions = (byte)actions; + d.reject = actions & DND_EXACTIMAGE ? CtrlCoreImg::DndNone() : MakeDragImage(CtrlCoreImg::DndNone(), sample); + if(actions & DND_COPY) + d.copy = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndCopy(), sample); + if(actions & DND_MOVE) + d.move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMoveX11(), sample); + d.SetMaster(*this); + d.data = &data; + d.action = DND_NONE; + d.fmts = Split(fmts, ';'); + dndloop = &d; + sDnDSource = this; + d.Run(); + sDnDSource = NULL; + SyncCaret(); + LLOG("DoDragAndDrop finished"); + return d.action; +} + +void Ctrl::SetSelectionSource(const char *fmts) {} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Draw.cpp b/rainbow/Turtle/Draw.cpp new file mode 100644 index 000000000..e45c16a35 --- /dev/null +++ b/rainbow/Turtle/Draw.cpp @@ -0,0 +1,105 @@ +#include + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +void SystemDraw::Put16(int x) +{ + result.Cat(LOBYTE(x)); + result.Cat(HIBYTE(x)); +} + +void SystemDraw::Put32(int x) +{ + Put16(LOWORD(x)); + Put16(HIWORD(x)); +} + +void SystemDraw::Put(Point p) +{// TODO: Clamp? + Put16(p.x); + Put16(p.y); +} + +void SystemDraw::Put(Size sz) +{ + Put((Point)sz); +} + +void SystemDraw::Put(const Rect& r) +{ + Put(r.TopLeft()); + Put(r.GetSize()); +} + +void SystemDraw::Put(const String& s) +{ + Put32(s.GetLength()); + result.Cat(s); +} + +Index SystemDraw::img_index[3]; + +int SystemDraw::GetImageI(int from, Index& img_index, int maxcount, SystemDraw& w, const Image& img) +{ + int64 id = img.GetSerialId(); + int q = img_index.Find(id); + if(q < 0) { + if(img_index.GetCount() < maxcount) { + q = img_index.GetCount(); + img_index.Add(id); + } + else { + q = Random(maxcount); + img_index.Set(q, id); + } + w.Put8(SETIMAGE); + w.Put16(q + from); + w.Put(img.GetSize()); + const RGBA *end = ~img + img.GetLength(); + for(const RGBA *s = ~img; s < end; s++) { + w.Put8(s->r); + w.Put8(s->g); + w.Put8(s->b); + w.Put8(s->a); + } + } + return q + from; +} + +int SystemDraw::GetImageI(SystemDraw& w, const Image& img) +{ + int area = img.GetWidth() * img.GetHeight(); + return area <= 64*64 ? GetImageI(0, img_index[0], 2048, w, img) : + area <= 512 * 512 ? GetImageI(2048, img_index[1], 64, w, img) : + GetImageI(2048 + 64, img_index[2], 8, w, img); +} + +void SystemDraw::PutImage(Point p, const Image& img, const Rect& src) +{ + int i = GetImageI(*this, img); + Put8(IMAGE); + Put16(i); + Put(p); + Put(src); +} + +void SystemDraw::PutRect(const Rect& r, Color color) +{ // TODO: Support InvertColor + if(color == InvertColor()) { + Put8(INVERTRECT); + Put(r); + } + else { + Put8(RECT); + Put(r); + Put8(color.GetR()); + Put8(color.GetG()); + Put8(color.GetB()); + } +} + +END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/Turtle/DrawDragRect.cpp b/rainbow/Turtle/DrawDragRect.cpp new file mode 100644 index 000000000..8126d3eb3 --- /dev/null +++ b/rainbow/Turtle/DrawDragRect.cpp @@ -0,0 +1,98 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +struct DrawDragRectInfo { + Rect rect1, rect2, clip; + int n; + int type; + int animation; +}; + +void DrawDragLine(SystemDraw& w, bool horz, int x, int y, int len, int n, const int *pattern, int animation) +{ + if(len <= 0) + return; + if(horz) + w.Clip(x, y, len, n); + else + w.Clip(x, y, n, len); + + (horz ? x : y) -= animation; + len += animation; + bool ch = false; + while(len > 0) { + int segment = pattern[ch]; + int d = segment + pattern[2]; + if(horz) { + w.DrawRect(x, y, segment, n, InvertColor()); + x += d; + } + else { + w.DrawRect(x, y, n, segment, InvertColor()); + y += d; + } + len -= d; + ch = !ch; + } + w.End(); +} + +void DrawDragFrame(SystemDraw& w, const Rect& r, int n, const int *pattern, int animation) +{ + DrawDragLine(w, true, r.left, r.top, r.GetWidth(), n, pattern, animation); + DrawDragLine(w, false, r.left, r.top + n, r.GetHeight() - 2 * n, n, pattern, animation); + DrawDragLine(w, false, r.right - n, r.top + n, r.GetHeight() - 2 * n, n, pattern, animation); + DrawDragLine(w, true, r.left, r.bottom - n, r.GetWidth(), n, pattern, animation); +} + +void DrawDragRect(Ctrl& q, const DrawDragRectInfo& f) +{ + _TODO_ + SystemDraw w; + Ctrl::PaintScene(w); + w.Clip(f.clip); + static int dashes[3][3] = { + { 32, 32, 0 }, + { 1, 1, 1 }, + { 5, 1, 2 }, + }; + const int *dash = dashes[minmax(f.type, 0, 2)]; + DrawDragFrame(w, f.rect1, f.n, dash, f.animation); + DrawDragFrame(w, f.rect2, f.n, dash, f.animation); +// w.End(); + Ctrl::PaintCaretCursor(w); +// SDL_GL_SwapWindow(screen.win); +} + +void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, int type, int animation) +{ + Ctrl *top = q.GetTopCtrl(); + if(top) { + Point off = q.GetScreenView().TopLeft(); + DrawDragRectInfo f; + f.rect1 = rect1.Offseted(off); + f.rect2 = rect2.Offseted(off); + f.clip = (clip & q.GetSize()).Offseted(off); + f.n = n; + f.type = type; + f.animation = animation; + DrawDragRect(*top, f); + } +} + +void FinishDragRect(Ctrl& q) +{ + SystemDraw w; + Ctrl::PaintScene(w); + Ctrl::PaintCaretCursor(w); + _TODO_ + //SDL_GL_SwapWindow(screen.win); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Event.cpp b/rainbow/Turtle/Event.cpp new file mode 100644 index 000000000..d05669696 --- /dev/null +++ b/rainbow/Turtle/Event.cpp @@ -0,0 +1,482 @@ +#include "Local.h" + +#include "Turtle.brc" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) DLOG(x) +#define LDUMP(x) DDUMP(x) +#define LTIMING(x) + +static Point MousePos; + +Size DesktopSize = Size(1000, 1000); + +StaticRect& Desktop() +{ + static StaticRect x; + return x; +} + +HttpHeader http; +TcpSocket server; +TcpSocket socket; +WebSocket websocket; + +String content; + + +void Ctrl::InitTelpp() +{ + if(!server.Listen(8088, 10)) { + LOG("Cannot open server port for listening\r\n"); + return; + } + LLOG("Starting to listen"); + socket.Timeout(20000); + for(;;) { + if(socket.Accept(server)) { + if(http.Read(socket)) { + LLOG("Accepted, header read"); + if(websocket.WebAccept(socket, http)) + break; + LLOG("Sending HTML"); + HttpResponse(socket, http.scgi, 200, "OK", "text/html", String(turtle_html, turtle_html_length)); + } + socket.Close(); + } + } + + LLOG("WebSocket connected"); + + Ctrl::GlobalBackBuffer(); + Ctrl::InitTimer(); + +#ifdef PLATFORM_POSIX + SetStdFont(ScreenSans(12)); //FIXME general handling +#endif + ChStdSkin(); + + Desktop().Color(Cyan()); + Desktop().SetRect(0, 0, DesktopSize.cx, DesktopSize.cy); + SetDesktop(Desktop()); +} + +void Ctrl::Reply() +{ + GuiLock __; + if(websocket.IsOpen()) { + TimerProc(GetTickCount()); + DefferedFocusSync(); + SyncCaret(); + SyncTopWindows(); + SweepMkImageCache(); + DoPaint(); +// String s = GZCompress(content); + String s = content; + websocket.SendBinary(s); + } +} + +bool Ctrl::IsWaitingEvent() +{ + GuiLock __; + Reply(); + return socket.Timeout(0).Peek() >= 0; +} + +bool Ctrl::ProcessEvents(bool *quit) +{ + GuiLock __; + LLOG("ProcessEvents"); + if(!IsWaitingEvent()) + return false; + + TimeStop tm; + LLOG("Trying to read socket"); + String event_queue = websocket.Recieve(); + LLOG("---- Process events"); + if(event_queue.GetCount()) + LOG(event_queue); + content.Clear(); + bool r = ProcessEventQueue(event_queue); + _TODO_ // Resolve eventloop exit issue + Reply(); + return r; +} + +void Ctrl::GuiSleep(int ms) +{ + GuiLock __; + Reply(); + ASSERT(IsMainThread()); +// LLOG("GuiSleep"); + int level = LeaveGuiMutexAll(); + Sleep(ms); _TODO_ + EnterGuiMutex(level); +} + +dword lastbdowntime[8] = {0}; +dword isdblclick[8] = {0}; + +void Ctrl::MouseEventFB(Ptr t, int event, Point p, int zdelta) +{ + if(!t->IsEnabled()) + return; + Rect rr = t->GetRect(); + if((event & Ctrl::ACTION) == DOWN) { + Ptr q = t; + TopWindowFrame *wf = dynamic_cast(~t); + if(wf) + q = wf->window; + if(q) q->ClickActivateWnd(); + if(q) q->SetForeground(); + if(ignoreclick) + return; + } + if(t) + t->DispatchMouse(event, p - rr.TopLeft(), zdelta); + if(t) + t->PostInput(); +} + +Ctrl *Ctrl::FindMouseTopCtrl() +{ + for(int i = topctrl.GetCount() - 1; i >= 0; i--) { + Ctrl *t = topctrl[i]; + if(t->GetRect().Contains(MousePos)) + return t->IsEnabled() ? t : NULL; + } + return desktop->IsEnabled() ? desktop : NULL; +} + +void Ctrl::SetCaret(int x, int y, int cx, int cy) +{ + GuiLock __; + caretx = x; + carety = y; + caretcx = cx; + caretcy = cy; + fbCaretTm = GetTickCount(); + SyncCaret(); +} + +void Ctrl::SyncCaret() +{ + CursorSync(); +} + +void Ctrl::CursorSync() +{ +// LLOG("@ CursorSync"); + Point p = GetMousePos() - fbCursorImage.GetHotSpot(); + Rect cr = Null; + if(focusCtrl && (((GetTickCount() - fbCaretTm) / 500) & 1) == 0) + cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy) + + focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView(); + if(fbCursorPos != p && !SystemCursor || cr != fbCaretRect) { + fbCaretRect = cr; + fbCursorPos = p; + Invalidate(); + } +} + +void Ctrl::PaintScene(SystemDraw& draw) +{ + if(!desktop) + return; + LLOG("@ DoPaint"); + LTIMING("DoPaint paint"); + draw.Init(DesktopSize); + draw.Begin(); + Vector invalid; + invalid.Add(DesktopSize); _TODO_ + for(int i = topctrl.GetCount() - 1; i >= 0; i--) { + Rect r = topctrl[i]->GetRect(); + Rect ri = GetClipBound(invalid, r); + if(!IsNull(ri)) { + draw.Clipoff(r); + topctrl[i]->UpdateArea(draw, ri - r.TopLeft()); + draw.End(); + Subtract(invalid, r); + draw.ExcludeClip(r); + } + } + Rect ri = GetClipBound(invalid, desktop->GetRect().GetSize()); + if(!IsNull(ri)) + desktop->UpdateArea(draw, ri); + draw.End(); +} + +void Ctrl::PaintCaretCursor(SystemDraw& draw) +{ + if(!IsNull(fbCaretRect)) + draw.DrawRect(fbCaretRect, InvertColor); + int64 q = fbCursorImage.GetAuxData(); + if(q) { + draw.Put8(SystemDraw::STD_CURSORIMAGE); + draw.Put8(clamp((int)q, 1, 16)); + } + else { + String h; + Point p = fbCursorImage.GetHotSpot(); + h << "url('data:image/png;base64," + << Base64Encode(PNGEncoder().SaveString(fbCursorImage)) + << "') " << p.x << ' ' << p.y << ", default"; + draw.Put8(SystemDraw::SETCURSORIMAGE); + draw.Put16(0); // _TODO_ Cursor cache + draw.Put(h); + draw.Put8(SystemDraw::CURSORIMAGE); + draw.Put16(0); // _TODO_ Cursor cache + } +} + +void Ctrl::DoPaint() +{ + if(!PaintLock) { + if(invalid && desktop) { + invalid = false; + SystemDraw draw; + PaintScene(draw); + PaintCaretCursor(draw); + content << String(draw.result); + } + } +} + +bool keyShift; +bool keyCtrl; +bool keyAlt; + +bool GetShift() { return keyShift; } +bool GetCtrl() { return keyCtrl; } +bool GetAlt() { return keyAlt; } +bool GetCapsLock() { return false; } // Impossible to implement + +dword fbKEYtoK(dword chr) { + chr = chr + K_DELTA; + if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY) + return chr; + if(GetCtrl()) chr |= K_CTRL; + if(GetAlt()) chr |= K_ALT; + if(GetShift()) chr |= K_SHIFT; + return chr; +/* + if(chr == SDLK_TAB) + chr = K_TAB; + else + if(chr == SDLK_SPACE) + chr = K_SPACE; + else + if(chr == SDLK_RETURN) + chr = K_RETURN; + else + chr = chr + K_DELTA; +*/ +} + +void Ctrl::ReadKeyMods(CParser& p) +{ + const char *s = p.GetPtr(); + if(*s) + keyShift = *s++ == '1'; + if(*s) + keyCtrl = *s++ == '1'; + if(*s) + keyAlt = *s++ == '1'; +} + +bool Ctrl::DoKeyFB(dword key, int cnt) +{ + LLOG("DoKeyFB [" << GetKeyDesc(key) << "] " << key << ", " << cnt); + + bool b = DispatchKey(key, cnt); + SyncCaret(); + Ctrl *desktop = GetDesktop(); + if(desktop) + desktop->PostInput(); + return b; +} + + +bool mouseLeft, mouseMiddle, mouseRight; +Point mouseDownPos; +int64 mouseDownTime; + +bool GetMouseLeft() { return mouseLeft; } +bool GetMouseRight() { return mouseRight; } +bool GetMouseMiddle() { return mouseMiddle; } + +void Ctrl::DoMouseFB(int event, Point p, int zdelta, CParser& cp) +{ + ReadKeyMods(cp); + MousePos = p; + int a = event & ACTION; + if(a == UP && Ctrl::ignoreclick) { + EndIgnore(); + return; + } + else + if(a == DOWN && ignoreclick) + return; + LLOG("### Mouse event: " << event << " position " << p << " zdelta " << zdelta << ", capture " << Upp::Name(captureCtrl)); + if(captureCtrl) + MouseEventFB(captureCtrl->GetTopCtrl(), event, p, zdelta); + else + for(int i = topctrl.GetCount() - 1; i >= 0; i--) { + Ptr t = topctrl[i]; + Rect rr = t->GetRect(); + if(rr.Contains(p)) { + MouseEventFB(t, event, p, zdelta); + return; + } + } + Ctrl *desktop = GetDesktop(); + if(desktop) { + desktop->DispatchMouse(event, p, zdelta); + desktop->PostInput(); + } +} + +static int sDistMax(Point a, Point b) +{ + return IsNull(a) ? INT_MAX : max(abs(a.x - b.x), abs(a.y - b.y)); +} + +Point ReadPoint(CParser& p) +{ + Point pt; + pt.x = p.ReadInt(); + pt.y = p.ReadInt(); + return pt; +} + +void Ctrl::DoMouseButton(int event, CParser& p) +{ + int button = p.ReadInt(); + Point pt = ReadPoint(p); + int64 tm = p.ReadInt64(); + (button == 0 ? mouseLeft : button == 2 ? mouseRight : mouseMiddle) = event == DOWN; + if(event == DOWN) + if(sDistMax(mouseDownPos, pt) < GUI_DragDistance() && tm - mouseDownTime < 800) { + event = DOUBLE; + mouseDownTime = 0; + } + else { + mouseDownPos = pt; + mouseDownTime = tm; + } + DoMouseFB(decode(button, 0, LEFT, 2, RIGHT, MIDDLE)|event, pt, 0, p); +} + +bool Ctrl::ProcessEventQueue(const String& event_queue) +{ + StringStream ss(event_queue); + while(!ss.IsEof()) { + String s = ss.GetLine(); + CParser p(s); + try { + if(p.Id("I")) + SystemDraw::ResetI(); + else + if(p.Id("R")) { + DesktopSize = ReadPoint(p); + Desktop().SetRect(0, 0, DesktopSize.cx, DesktopSize.cy); + } + if(p.Id("M")) { + Point pt = ReadPoint(p); + int64 tm = p.ReadInt64(); + DoMouseFB(MOUSEMOVE, pt, 0, p); + } + else + if(p.Id("W")) { + double w = p.ReadDouble(); + Point pt = ReadPoint(p); + int64 tm = p.ReadInt64(); + DoMouseFB(MOUSEWHEEL, pt, w < 0 ? 120 : -120, p); + } + else + if(p.Id("O")) { + mouseLeft = mouseMiddle = mouseRight = false; + mouseDownTime = 0; + } + else + if(p.Id("D")) { + DoMouseButton(DOWN, p); + } + else + if(p.Id("U")) { + DoMouseButton(UP, p); + } + else + if(p.Id("K")) { + int code = p.ReadInt(); + int which = p.ReadInt(); + ReadKeyMods(p); + DoKeyFB(fbKEYtoK(which), 1); + } + else + if(p.Id("k")) { + int code = p.ReadInt(); + int which = p.ReadInt(); + ReadKeyMods(p); + DoKeyFB(K_KEYUP|fbKEYtoK(which), 1); + } + else + if(p.Id("C")) { + int code = p.ReadInt(); + int which = p.ReadInt(); + ReadKeyMods(p); + if(which && !keyAlt && !keyCtrl) + DoKeyFB(which, 1); + } + } + catch(CParser::Error) {} + } + return true; +} + +Point GetMousePos() { + return MousePos; +} + +void Ctrl::EventLoop(Ctrl *ctrl) +{ + GuiLock __; + Reply(); + ASSERT(IsMainThread()); + ASSERT(LoopLevel == 0 || ctrl); + LoopLevel++; + LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN); + Ptr ploop; + if(ctrl) { + ploop = LoopCtrl; + LoopCtrl = ctrl; + ctrl->inloop = true; + } + + bool quit = false; + int64 loopno = ++EventLoopNo; + ProcessEvents(&quit); + while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount())) + { +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep"); + SyncCaret(); + GuiSleep(20); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents"); + ProcessEvents(&quit); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents"); +// LDUMP(loopno); + } + + if(ctrl) + LoopCtrl = ploop; + LoopLevel--; + LLOG(LOG_END << "Leaving event loop "); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/FB.iml b/rainbow/Turtle/FB.iml new file mode 100644 index 000000000..c36090ae7 --- /dev/null +++ b/rainbow/Turtle/FB.iml @@ -0,0 +1,63 @@ +PREMULTIPLIED +IMAGE_ID(Arrow) +IMAGE_ID(IBeam) +IMAGE_ID(Wait) +IMAGE_ID(No) +IMAGE_ID(SizeAll) +IMAGE_ID(SizeHorz) +IMAGE_ID(SizeRight) +IMAGE_ID(SizeLeft) +IMAGE_ID(SizeVert) +IMAGE_ID(SizeTopLeft) +IMAGE_ID(SizeTop) +IMAGE_ID(SizeTopRight) +IMAGE_ID(SizeBottomLeft) +IMAGE_ID(SizeBottom) +IMAGE_ID(SizeBottomRight) +IMAGE_ID(overlap) +IMAGE_ID(maximize) +IMAGE_ID(close) +IMAGE_ID(bgtitle) +IMAGE_ID(title) +IMAGE_ID(border) +IMAGE_ID(Hand) + +IMAGE_BEGIN_DATA +IMAGE_DATA(120,156,237,90,61,104,20,65,20,30,77,162,9,92,144,248,135,160,133,117,42,177,18,21,4,171,84,65,76,22,4,149) +IMAGE_DATA(136,17,37,49,66,4,13,40,72,34,4,145,128,120,133,196,20,49,30,24,11,207,104,33,105,196,4,114,133,34,66,68) +IMAGE_DATA(52,129,67,20,65,4,145,52,218,217,61,103,214,157,117,118,110,126,222,91,247,240,135,157,229,177,55,51,223,247,230,205) +IMAGE_DATA(247,222,206,94,244,88,129,109,98,162,173,97,171,196,13,184,5,12,223,128,200,129,114,153,196,129,239,223,183,195,244,244) +IMAGE_DATA(22,44,7,190,125,219,13,95,191,238,131,169,169,29,24,14,172,172,28,128,47,95,186,225,243,231,195,48,62,190,223,199) +IMAGE_DATA(129,79,159,122,225,227,199,83,240,225,195,25,120,255,254,28,20,139,7,93,28,120,247,238,60,188,125,123,1,170,213,97) +IMAGE_DATA(88,90,186,2,175,95,95,131,177,177,99,54,14,44,47,143,194,155,55,87,225,213,171,235,240,242,229,4,188,120,113,7) +IMAGE_DATA(158,63,159,134,209,209,126,19,135,99,138,176,184,120,131,227,38,225,217,179,123,176,176,176,16,217,3,24,30,30,208,57) +IMAGE_DATA(220,215,4,199,77,194,211,167,119,160,82,121,24,98,75,165,146,196,169,22,226,43,149,91,220,74,48,63,127,23,230,230) +IMAGE_DATA(238,195,227,199,143,156,251,125,242,228,54,92,188,120,58,246,51,52,52,232,196,15,13,245,169,243,194,96,112,112,64,141) +IMAGE_DATA(33,129,55,105,208,223,127,210,170,167,97,44,92,163,183,247,152,109,13,83,131,158,158,35,148,186,13,215,8,130,110,210) +IMAGE_DATA(26,93,93,7,41,248,128,16,143,185,53,177,117,108,53,91,27,26,211,18,47,76,54,237,115,28,176,214,255,231,199,44) +IMAGE_DATA(251,173,209,133,21,184,112,77,92,180,166,164,112,88,11,51,183,245,222,184,211,20,44,147,248,109,101,179,41,248,120,83) +IMAGE_DATA(155,175,93,50,114,196,152,152,211,240,65,203,174,157,176,254,236,137,4,71,124,22,99,98,142,25,158,36,149,227,193,38) +IMAGE_DATA(56,98,125,97,30,108,204,209,180,115,98,9,254,41,241,83,245,161,234,79,201,47,181,126,104,245,217,198,175,230,232,178) +IMAGE_DATA(9,103,33,163,143,70,132,89,147,230,193,81,230,93,241,186,252,164,225,215,36,80,233,99,215,183,125,166,196,111,138,139) +IMAGE_DATA(194,151,205,231,195,199,247,249,192,240,77,62,108,251,196,232,100,251,236,203,117,205,97,237,136,203,23,131,105,140,194,255) +IMAGE_DATA(157,231,129,82,79,212,231,22,227,203,204,69,28,72,63,189,242,38,94,217,226,142,8,194,200,47,151,203,130,15,209,157) +IMAGE_DATA(228,71,229,243,110,42,63,81,252,9,97,162,109,185,14,139,68,12,160,180,200,101,220,92,177,168,92,137,83,125,216,48) +IMAGE_DATA(166,253,171,241,234,62,212,125,170,250,232,250,233,205,54,166,250,49,233,135,53,25,119,22,113,100,161,71,86,121,201,170) +IMAGE_DATA(62,212,102,210,153,82,167,186,62,204,160,95,26,63,105,248,170,31,148,6,109,252,107,127,51,107,8,77,39,251,4,176) +IMAGE_DATA(9,109,43,22,155,15,234,195,99,106,236,15,60,60,152,56,178,208,35,147,188,228,137,206,19,157,39,250,127,74,244,90) +IMAGE_DATA(158,234,134,40,213,186,67,87,2,93,137,241,9,174,196,155,16,72,235,199,65,203,57,211,134,254,230,57,215,254,92,186) +IMAGE_DATA(184,244,116,229,65,205,83,77,254,90,249,181,38,186,106,235,19,87,61,166,96,41,28,204,151,17,149,211,222,222,142,230) +IMAGE_DATA(72,49,132,117,118,118,122,121,74,18,2,41,40,134,167,182,44,121,152,167,88,231,97,79,15,201,19,122,178,72,91,44) +IMAGE_DATA(135,41,249,195,228,91,47,106,12,199,88,139,249,201,84,191,57,215,254,92,186,212,253,100,114,53,107,165,120,56,212,138) +IMAGE_DATA(76,83,249,212,39,140,250,36,83,79,12,204,201,164,36,27,125,2,74,61,169,39,173,212,132,114,162,51,150,254,205,193) +IMAGE_DATA(8,111,40,106,77,229,5,155,23,172,147,195,254,182,130,205,95,165,245,155,115,237,207,165,75,221,95,165,105,42,69,110) +IMAGE_DATA(66,15,150,194,201,191,228,219,121,174,19,208,198,251,175,191,228,23,248,149,81,3,143,153,240,46,95,105,241,152,56,116) +IMAGE_DATA(188,111,205,172,240,24,125,234,165,139,58,70,201,19,190,101,80,76,190,224,40,98,153,48,57,62,123,60,37,95,248,246) +IMAGE_DATA(187,197,180,177,177,49,216,219,218,10,226,142,153,19,253,61,220,244,113,137,149,115,182,113,209,55,141,153,214,13,231,11) +IMAGE_DATA(133,208,108,216,4,71,96,35,156,248,108,195,82,241,148,120,168,251,77,171,39,54,95,164,214,200,47,217,186,186,38,224) +IMAGE_DATA(80,223,12,28,189,60,3,199,111,206,0,181,31,59,107,8,255,111,102,4,90,218,203,176,33,88,134,109,195,226,37,76) +IMAGE_DATA(236,139,50,111,226,87,244,183,44,246,121,74,188,249,125,77,252,166,90,197,255,250,77,182,217,70,70,70,114,124,157,240) +IMAGE_DATA(178,239,179,52,181,16,22,147,227,31,70,228,175,156,212,187,11,7,197,98,49,113,183,112,226,249,106,181,154,184,91,56) +IMAGE_DATA(53,56,121,87,214,97,234,198,108,120,101,157,56,142,142,142,14,52,94,244,165,97,240,179,179,179,9,142,201,20,124,32) +IMAGE_DATA(98,17,49,33,241,94,142,88,95,195,199,28,19,94,140,219,114,230,139,229,7,18,241,124,50,0,0,0,0,0,0,0) +IMAGE_END_DATA(1184, 22) diff --git a/rainbow/Turtle/Gui.h b/rainbow/Turtle/Gui.h new file mode 100644 index 000000000..4c94007a9 --- /dev/null +++ b/rainbow/Turtle/Gui.h @@ -0,0 +1,358 @@ +#define GUI_TURTLE + +NAMESPACE_UPP + +class SystemDraw : public Draw { +public: + virtual dword GetInfo() const; + virtual Size GetPageSize() const; + + virtual void BeginOp(); + virtual void EndOp(); + virtual void OffsetOp(Point p); + virtual bool ClipOp(const Rect& r); + virtual bool ClipoffOp(const Rect& r); + virtual bool ExcludeClipOp(const Rect& r); + virtual bool IntersectClipOp(const Rect& r); + virtual bool IsPaintingOp(const Rect& r) const; + virtual Rect GetPaintRect() const; + + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); + virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor); + virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, + const int *disjunct_polygon_counts, int dpcc, + Color color, int width, Color outline, + uint64 pattern, Color doxor); + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx); + + virtual Size GetNativeDpi() const; + virtual void BeginNative(); + virtual void EndNative(); + + virtual int GetCloffLevel() const; + +private: + Size pageSize; + Size nativeSize; + Size nativeDpi; + bool palette:1; + bool color16:1; + bool is_mono:1; + int native; + + friend class ImageDraw; + friend class FontInfo; + friend class Font; + + friend void StaticExitDraw_(); + + Point actual_offset_bak; + + struct Cloff : Moveable { + Point org; + HRGN hrgn; + Rect drawingclip; + }; + + Array cloff; + Rect drawingclip; + + COLORREF lastTextColor; + Color lastColor; + HBRUSH orgBrush; + HBRUSH actBrush; + HPEN orgPen; + HPEN actPen; + int lastPen; + Color lastPenColor; + + void Unselect0(); + void Cinit(); + + void LoadCaps(); + void SetPrinterMode(); + void Reset(); + void SetOrg(); + friend HPALETTE GetQlibPalette(); + void DotsMode(); + + static void InitColors(); + + friend class BackDraw; + friend class ScreenDraw; + friend class PrintDraw; + +protected: + dword style; + HDC handle; + Point actual_offset; + + SystemDraw(); + void Init(); + void InitClip(const Rect& clip); + +public: + static Rect GetVirtualScreenArea(); + + static void SetAutoPalette(bool ap); + static bool AutoPalette(); + bool PaletteMode() { return palette; } + + static void Flush() { GdiFlush(); } + + COLORREF GetColor(Color color) const; + + Point GetOffset() const { return actual_offset; } + +#ifndef PLATFORM_WINCE + Point LPtoDP(Point p) const; + Point DPtoLP(Point p) const; + Rect LPtoDP(const Rect& r) const; + Rect DPtoLP(const Rect& r) const; +#endif + + void SetColor(Color color); + void SetDrawPen(int width, Color color); + + Size GetSizeCaps(int i, int j) const; + HDC BeginGdi(); + void EndGdi(); + HDC GetHandle() { return handle; } + operator HDC() const { return handle; } + void Unselect(); + void Attach(HDC ahandle) { handle = ahandle; Init(); } + HDC Detach() { Unselect(); HDC h = handle; handle = NULL; return h; } + + SystemDraw(HDC hdc); + virtual ~SystemDraw(); + + bool CanSetSurface() { return IsGui() && IsWinNT(); } +}; + +#ifndef PLATFORM_WINCE +class WinMetaFile { + Size size; + HENHMETAFILE hemf; + + void Init(); + +public: + void Attach(HENHMETAFILE emf); + HENHMETAFILE Detach(); + + void Set(const void *data, dword len); + void Set(const String& data) { Set(~data, data.GetCount()); } + + String Get() const; + + operator bool() const { return hemf; } + void SetSize(const Size& sz) { size = sz; } + Size GetSize() const { return hemf ? size : Size(0, 0); } + + void Clear(); + + void Paint(Draw& w, const Rect& r) const; + void Paint(Draw& w, int x, int y, int cx, int cy) const; + + void Serialize(Stream& s); + + void ReadClipboard(); + void WriteClipboard() const; + void Load(const char *file) { Set(LoadFile(file)); } + + WinMetaFile() { Init(); } + WinMetaFile(HENHMETAFILE hemf); + WinMetaFile(HENHMETAFILE hemf, Size sz); + WinMetaFile(const char *file); + WinMetaFile(void *data, int len); + WinMetaFile(const String& data); + + ~WinMetaFile() { Clear(); } + + HENHMETAFILE GetHEMF() const { return hemf; } +}; + +class WinMetaFileDraw : public SystemDraw { + Size size; + +public: + bool Create(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + bool Create(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFile Close(); + + WinMetaFileDraw() {} + WinMetaFileDraw(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + ~WinMetaFileDraw(); +}; + +void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf); +void DrawWMF(Draw& w, int x, int y, const String& wmf); +Drawing LoadWMF(const char *path, int cx, int cy); +Drawing LoadWMF(const char *path); + +String AsWMF(const Drawing& iw); + +#endif + +class ScreenDraw : public SystemDraw { +public: + ScreenDraw(bool ic = false); + ~ScreenDraw(); +}; + +#ifndef PLATFORM_WINCE +class PrintDraw : public SystemDraw { +public: + virtual void StartPage(); + virtual void EndPage(); + +private: + bool aborted; + + void InitPrinter(); +public: + PrintDraw(HDC hdc, const char *jobname); + ~PrintDraw(); +}; +#endif + +inline bool BitBlt(HDC ddc, Point d, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return BitBlt(ddc, d.x, d.y, s.Width(), s.Height(), sdc, s.left, s.top, rop); } + +inline bool StretchBlt(HDC ddc, const Rect& r, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return StretchBlt(ddc, r.left, r.top, r.Width(), r.Height(), sdc, s.left, s.top, s.Width(), s.Height(), rop); } + +inline bool PatBlt(HDC dc, const Rect& r, dword rop = PATCOPY) +{ return PatBlt(dc, r.left, r.top, r.Width(), r.Height(), rop); } + +inline void MoveTo(HDC hdc, Point pt) { MoveToEx(hdc, pt.x, pt.y, 0); } +inline void LineTo(HDC hdc, Point pt) { LineTo(hdc, pt.x, pt.y); } + +inline void DrawLine(HDC hdc, Point p, Point q) { MoveTo(hdc, p); LineTo(hdc, q); } +inline void DrawLine(HDC hdc, int px, int py, int qx, int qy) { MoveToEx(hdc, px, py, 0); LineTo(hdc, qx, qy); } + +#ifndef PLATFORM_WINCE +inline void DrawArc(HDC hdc, const Rect& rc, Point p, Point q){ Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, p.x, p.y, q.x, q.y); } +#endif +inline void DrawCircle(HDC hdc, int x, int y, int radius) { Ellipse(hdc, x - radius, y - radius, x + radius + 1, y + radius + 1); } +inline void DrawCircle(HDC hdc, Point centre, int radius) { DrawCircle(hdc, centre.x, centre.y, radius); } +inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +HDC ScreenHDC(); +HPALETTE GetQlibPalette(); + +Image Win32Icon(LPCSTR id, int iconsize = 0); +Image Win32Icon(int id, int iconsize = 0); +Image Win32Cursor(LPCSTR id); +Image Win32Cursor(int id); +HICON IconWin32(const Image& img, bool cursor = false); +Image Win32DllIcon(const char *dll, int ii, bool large); + +class BackDraw : public SystemDraw { +public: + virtual bool IsPaintingOp(const Rect& r) const; + +protected: + HBITMAP hbmpold; + HBITMAP hbmp; + + Size size; + Draw *painting; + Point painting_offset; + +public: + void Put(SystemDraw& w, int x, int y); + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy); + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy(); + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SystemDraw { + Size size; + + struct Section { + HDC dc; + HBITMAP hbmp, hbmpOld; + RGBA *pixels; + + void Init(int cx, int cy); + ~Section(); + }; + + Section rgb; + Section a; + SystemDraw alpha; + + + bool has_alpha; + + void Init(); + Image Get(bool pm) const; + +public: + Draw& Alpha(); + + operator Image() const; + + Image GetStraight() const; + + ImageDraw(Size sz); + ImageDraw(int cx, int cy); + ~ImageDraw(); +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_KEYCODES_INCLUDE "Win32Keys.h" + + +#define GUIPLATFORM_CTRL_TOP_DECLS \ + HWND hwnd; \ + UDropTarget *dndtgt; \ + + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE "Win32Ctrl.h" + + +#define GUIPLATFORM_PASTECLIP_DECLS \ + UDropTarget *dt; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE "Win32Top.h" + +NAMESPACE_UPP + +inline unsigned GetHashValue(const HWND& hwnd) +{ + return (unsigned)(intptr_t)hwnd; +} +END_UPP_NAMESPACE + +#ifdef PLATFORM_WIN32 +#ifndef PLATFORM_WINCE + +#include + +#endif +#endif + +#define GUIPLATFORM_INCLUDE_AFTER "Win32GuiA.h" diff --git a/rainbow/Turtle/Image.cpp b/rainbow/Turtle/Image.cpp new file mode 100644 index 000000000..7c2f58f11 --- /dev/null +++ b/rainbow/Turtle/Image.cpp @@ -0,0 +1,47 @@ +#include + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LTIMING(x) // RTIMING(x) + +void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels) +{ + GuiLock __; + // Empty as CanSetSurface is false +} + +void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff) +{ + GuiLock __; + // Empty as CanSetSurface is false +} + +#define IMAGECLASS FBImg +#define IMAGEFILE +#include + +#define STD_CURSOR(name, sdl) \ +Image Image::name() { static Image img; ONCELOCK { img = FBImg::name(); img.SetAuxData(sdl); } return img; } + +STD_CURSOR(Arrow, 1) +STD_CURSOR(Wait, 2) +STD_CURSOR(IBeam, 3) +STD_CURSOR(No, 4) +STD_CURSOR(SizeAll, 5) +STD_CURSOR(SizeHorz, 6) +STD_CURSOR(SizeVert, 7) +STD_CURSOR(SizeTopLeft, 8) +STD_CURSOR(SizeTop, 9) +STD_CURSOR(SizeTopRight, 10) +STD_CURSOR(SizeLeft, 11) +STD_CURSOR(SizeRight, 12) +STD_CURSOR(SizeBottomLeft, 13) +STD_CURSOR(SizeBottom, 14) +STD_CURSOR(SizeBottomRight, 15) +STD_CURSOR(Hand, 16) + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Keys.h b/rainbow/Turtle/Keys.h new file mode 100644 index 000000000..aae3bc005 --- /dev/null +++ b/rainbow/Turtle/Keys.h @@ -0,0 +1,113 @@ +#define WEBKEY(x) x + +K_BACK = WEBKEY(8) + K_DELTA, +K_BACKSPACE = WEBKEY(8) + K_DELTA, + +//handled extra in fbKEYtoK +K_TAB = 9, //SDLK_TAB, + +K_SPACE = 32, //SDLK_SPACE, + +K_RETURN = 13, //SDLK_RETURN, +K_ENTER = K_RETURN, + +K_SHIFT_KEY = WEBKEY(16) + K_DELTA, +K_CTRL_KEY = WEBKEY(17) + K_DELTA, +K_ALT_KEY = WEBKEY(18) + K_DELTA, + +K_CAPSLOCK = WEBKEY(20) + K_DELTA, +K_ESCAPE = WEBKEY(27) + K_DELTA, +K_PRIOR = WEBKEY(33) + K_DELTA, +K_PAGEUP = WEBKEY(33) + K_DELTA, +K_NEXT = WEBKEY(34) + K_DELTA, +K_PAGEDOWN = WEBKEY(34) + K_DELTA, +K_END = WEBKEY(35) + K_DELTA, +K_HOME = WEBKEY(36) + K_DELTA, +K_LEFT = WEBKEY(37) + K_DELTA, +K_UP = WEBKEY(38) + K_DELTA, +K_RIGHT = WEBKEY(39) + K_DELTA, +K_DOWN = WEBKEY(40) + K_DELTA, +K_INSERT = WEBKEY(45) + K_DELTA, +K_DELETE = WEBKEY(46) + K_DELTA, + +K_NUMPAD0 = WEBKEY(96) + K_DELTA, +K_NUMPAD1 = WEBKEY(97) + K_DELTA, +K_NUMPAD2 = WEBKEY(98) + K_DELTA, +K_NUMPAD3 = WEBKEY(99) + K_DELTA, +K_NUMPAD4 = WEBKEY(100) + K_DELTA, +K_NUMPAD5 = WEBKEY(101) + K_DELTA, +K_NUMPAD6 = WEBKEY(102) + K_DELTA, +K_NUMPAD7 = WEBKEY(103) + K_DELTA, +K_NUMPAD8 = WEBKEY(104) + K_DELTA, +K_NUMPAD9 = WEBKEY(105) + K_DELTA, +K_MULTIPLY = WEBKEY(106) + K_DELTA, +K_ADD = WEBKEY(107) + K_DELTA, +K_SEPARATOR = WEBKEY(108) + K_DELTA, +K_SUBTRACT = WEBKEY(109) + K_DELTA, +K_DECIMAL = WEBKEY(110) + K_DELTA, +K_DIVIDE = WEBKEY(111) + K_DELTA, +K_SCROLL = WEBKEY(145) + K_DELTA, + +K_F1 = WEBKEY(112) + K_DELTA, +K_F2 = WEBKEY(113) + K_DELTA, +K_F3 = WEBKEY(114) + K_DELTA, +K_F4 = WEBKEY(115) + K_DELTA, +K_F5 = WEBKEY(116) + K_DELTA, +K_F6 = WEBKEY(117) + K_DELTA, +K_F7 = WEBKEY(118) + K_DELTA, +K_F8 = WEBKEY(119) + K_DELTA, +K_F9 = WEBKEY(120) + K_DELTA, +K_F10 = WEBKEY(121) + K_DELTA, +K_F11 = WEBKEY(122) + K_DELTA, +K_F12 = WEBKEY(123) + K_DELTA, + +K_A = WEBKEY('A') + K_DELTA, +K_B = WEBKEY('B') + K_DELTA, +K_C = WEBKEY('C') + K_DELTA, +K_D = WEBKEY('D') + K_DELTA, +K_E = WEBKEY('E') + K_DELTA, +K_F = WEBKEY('F') + K_DELTA, +K_G = WEBKEY('G') + K_DELTA, +K_H = WEBKEY('H') + K_DELTA, +K_I = WEBKEY('I') + K_DELTA, +K_J = WEBKEY('J') + K_DELTA, +K_K = WEBKEY('K') + K_DELTA, +K_L = WEBKEY('L') + K_DELTA, +K_M = WEBKEY('M') + K_DELTA, +K_N = WEBKEY('N') + K_DELTA, +K_O = WEBKEY('O') + K_DELTA, +K_P = WEBKEY('P') + K_DELTA, +K_Q = WEBKEY('Q') + K_DELTA, +K_R = WEBKEY('R') + K_DELTA, +K_S = WEBKEY('S') + K_DELTA, +K_T = WEBKEY('T') + K_DELTA, +K_U = WEBKEY('U') + K_DELTA, +K_V = WEBKEY('V') + K_DELTA, +K_W = WEBKEY('W') + K_DELTA, +K_X = WEBKEY('X') + K_DELTA, +K_Y = WEBKEY('Y') + K_DELTA, +K_Z = WEBKEY('Z') + K_DELTA, +K_0 = WEBKEY('0') + K_DELTA, +K_1 = WEBKEY('1') + K_DELTA, +K_2 = WEBKEY('2') + K_DELTA, +K_3 = WEBKEY('3') + K_DELTA, +K_4 = WEBKEY('4') + K_DELTA, +K_5 = WEBKEY('5') + K_DELTA, +K_6 = WEBKEY('6') + K_DELTA, +K_7 = WEBKEY('7') + K_DELTA, +K_8 = WEBKEY('8') + K_DELTA, +K_9 = WEBKEY('9') + K_DELTA, + +K_CTRL_LBRACKET = K_CTRL|219|K_DELTA, +K_CTRL_RBRACKET = K_CTRL|221|K_DELTA, +K_CTRL_MINUS = K_CTRL|189|K_DELTA, +K_CTRL_GRAVE = K_CTRL|192|K_DELTA, +K_CTRL_SLASH = K_CTRL|191|K_DELTA, +K_CTRL_BACKSLASH = K_CTRL|220|K_DELTA, +K_CTRL_COMMA = K_CTRL|188|K_DELTA, +K_CTRL_PERIOD = K_CTRL|190|K_DELTA, +K_CTRL_SEMICOLON = K_CTRL|59|K_DELTA, +K_CTRL_EQUAL = K_CTRL|61|K_DELTA, +K_CTRL_APOSTROPHE= K_CTRL|222|K_DELTA, + +K_BREAK = WEBKEY(3) + K_DELTA, // Is it really? diff --git a/rainbow/Turtle/Local.h b/rainbow/Turtle/Local.h new file mode 100644 index 000000000..f1511f677 --- /dev/null +++ b/rainbow/Turtle/Local.h @@ -0,0 +1,63 @@ +#include + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +class TopWindowFrame : public Ctrl { +public: + virtual void Layout(); + virtual void Paint(Draw& w); + virtual Image CursorImage(Point p, dword keyflags); + virtual void LeftDown(Point p, dword keyflags); + virtual void LeftHold(Point p, dword keyflags); + virtual void LeftDouble(Point p, dword keyflags); + virtual void MouseMove(Point p, dword keyflags); + virtual void CancelMode(); + virtual void LeftUp(Point p, dword keyflags); + +private: + Point dir; + Point startpos; + Rect startrect; + + bool maximized; + Rect overlapped; + + bool holding; + TimeCallback hold; + + Point GetDragMode(Point p); + Image GetDragImage(Point dragmode); + void StartDrag(); + Rect Margins() const; + Rect ComputeClient(Rect r); + void Hold(); + + typedef TopWindowFrame CLASSNAME; + +public: + String title; + Button close, maximize; + Image icon; + Size minsize; + bool sizeable; + TopWindow *window; + + void SetTitle(const String& s) { title = s; Refresh(); } + Rect GetClient() const; + void SetClient(Rect r); + void GripResize(); + + void Maximize(); + void Overlap(); + void ToggleMaximize(); + bool IsMaximized() const { return maximized; } + void SyncRect(); + + TopWindowFrame(); +}; + +END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/Turtle/Socket.cpp b/rainbow/Turtle/Socket.cpp new file mode 100644 index 000000000..c2904be03 --- /dev/null +++ b/rainbow/Turtle/Socket.cpp @@ -0,0 +1,12 @@ +#include "Local.h" + + +#define LLOG(x) DLOG(x) + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Top.cpp b/rainbow/Turtle/Top.cpp new file mode 100644 index 000000000..7c2cdbca8 --- /dev/null +++ b/rainbow/Turtle/Top.cpp @@ -0,0 +1,152 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +void TopWindow::SyncFrameRect(const Rect& r) +{ + frame->SetClient(r); +} + +void TopWindow::DestroyFrame() +{ + if(frame->IsOpen()) + frame->DestroyWnd(); +} + +void TopWindow::GripResize() +{ + frame->GripResize(); +} + +void TopWindow::SyncSizeHints() +{ + SyncCaption(); +} + +void TopWindow::SyncTitle() +{ + SyncCaption(); +} + +void TopWindow::SyncCaption() +{ + GuiLock __; + frame->title = title.ToString(); +#ifdef _DEBUG + frame->title = "TELPP"; +#endif + frame->minsize = minsize; + frame->close.Show(!noclosebox); + frame->maximize.Show(maximizebox); + frame->sizeable = sizeable; + frame->RefreshLayout(); + frame->Refresh(); + frame->close <<= Proxy(WhenClose); + frame->icon = icon; + frame->Enable(IsEnabled()); +} + +void TopWindow::State(int reason) +{ + SyncCaption(); +} + +void TopWindow::SyncRect() +{ + frame->SyncRect(); + Rect r = frame->GetClient(); + if(r != GetRect()) + SetRect(r); +} + +void TopWindow::Open(Ctrl *owner) +{ + GuiLock __; + LLOG("Open " << Upp::Name(owner)); + Rect r = GetRect(); + if(r.IsEmpty()) + SetRect(GetDefaultWindowRect()); + else + if(r.left == 0 && r.top == 0) + if(owner && center == 1) + SetRect(owner->GetRect().CenterRect(r.GetSize())); + else + if(center) + SetRect(GetWorkArea().CenterRect(r.GetSize())); + frame->SetClient(GetRect()); + frame->window = this; + frame->PopUp(owner, false, true); + PopUp(frame, false, true); + popup = false; + SetRect(frame->GetClient()); + SyncCaption(); + if(state == MAXIMIZED) + frame->Maximize(); +} + +void TopWindow::Open() +{ + Open(GetActiveCtrl()); +} + +void TopWindow::OpenMain() +{ + Open(NULL); +} + +void TopWindow::Minimize(bool effect) +{ +// state = MINIMIZED; +} + +TopWindow& TopWindow::FullScreen(bool b) +{ + return *this; +} + +void TopWindow::Maximize(bool effect) +{ + state = MAXIMIZED; + frame->Maximize(); +} + +void TopWindow::Overlap(bool effect) +{ + GuiLock __; + state = OVERLAPPED; + frame->Overlap(); +} + +TopWindow& TopWindow::TopMost(bool b, bool stay_top) +{ + GuiLock __; + return *this; +} + +bool TopWindow::IsTopMost() const +{ + return true; +} + +void TopWindow::GuiPlatformConstruct() +{ + frame = new TopWindowFrame; +} + +void TopWindow::GuiPlatformDestruct() +{ + delete frame; +} + +void TopWindow::SerializePlacement(Stream& s, bool reminimize) +{ + GuiLock __; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Top.h b/rainbow/Turtle/Top.h new file mode 100644 index 000000000..2e9b12c16 --- /dev/null +++ b/rainbow/Turtle/Top.h @@ -0,0 +1,16 @@ +//$ class TopWindow { +public: + virtual void State(int reason); + +private: + TopWindowFrame *frame; + + void SyncRect(); + void SyncFrameRect(const Rect& r); + void DestroyFrame(); + + friend class Ctrl; + +public: + void GripResize(); +//$ }; diff --git a/rainbow/Turtle/TopFrame.cpp b/rainbow/Turtle/TopFrame.cpp new file mode 100644 index 000000000..bc3cf77de --- /dev/null +++ b/rainbow/Turtle/TopFrame.cpp @@ -0,0 +1,236 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LDUMP(x) //DDUMP(x) + +TopWindowFrame::TopWindowFrame() +{ + close.SetImage(FBImg::close()); + close.EdgeStyle(); + Add(close); + maximize.SetImage(FBImg::maximize()); + maximize.EdgeStyle(); + Add(maximize); + maximize <<= THISBACK(ToggleMaximize); + maximized = false; + sizeable = false; + holding = false; +} + +void TopWindowFrame::SyncRect() +{ + if(maximized) { + Size sz = GetWorkArea().GetSize(); + if(GetRect().GetSize() != sz) + SetRect(sz); + } +} + +void TopWindowFrame::Maximize() +{ + if(!maximized && maximize.IsShown()) { + maximized = true; + overlapped = GetRect(); + SetRect(GetWorkArea().GetSize()); + maximize.SetImage(FBImg::overlap()); + } +} + +void TopWindowFrame::Overlap() +{ + if(maximized && maximize.IsShown()) { + maximized = false; + SetRect(overlapped); + maximize.SetImage(FBImg::maximize()); + } +} + +void TopWindowFrame::ToggleMaximize() +{ + if(maximized) + Overlap(); + else + Maximize(); +} + +Rect TopWindowFrame::Margins() const +{ + return maximized ? Rect(0, 0, 0, 0) : ChMargins(FBImg::border()); +} + +void TopWindowFrame::Paint(Draw& w) +{ + Size sz = GetSize(); + Rect m = Margins(); + int c = GetStdFontCy() + 4; + ChPaintEdge(w, sz, FBImg::border()); + ChPaint(w, m.left, m.top, sz.cx - m.left - m.right, GetStdFontCy() + 4, + window->IsForeground() ? FBImg::title() : FBImg::bgtitle()); + int tx = m.left + 2; + int tcx = sz.cx - m.left - m.right - 4 - c * (close.IsShown() + maximize.IsShown()); + if(!IsNull(icon)) { + Image h = icon; + if(h.GetWidth() > c || h.GetHeight() > c) + h = Rescale(h, GetFitSize(h.GetSize(), Size(c))); + w.DrawImage(tx, m.top + 2, h); + tx += c; + tcx -= c; + } + DrawTextEllipsis(w, tx, m.top + 2, tcx, title, "..", StdFont(), SColorHighlightText()); +} + +void TopWindowFrame::Layout() +{ + Size sz = GetSize(); + Rect m = Margins(); + int c = GetStdFontCy() + 4; + int x = sz.cx - m.right; + if(close.IsShown()) + close.SetRect(x -= c, m.top, c, c); + if(maximize.IsShown()) + maximize.SetRect(x -= c, m.top, c, c); +} + +Rect TopWindowFrame::GetClient() const +{ + Rect r = GetRect(); + Rect m = Margins(); + r.left += m.left; + r.right -= m.right; + r.top += m.top; + r.bottom -= m.bottom; + r.top += GetStdFontCy() + 4; + return r; +} + +Rect TopWindowFrame::ComputeClient(Rect r) +{ + Rect m = Margins(); + r.left -= m.left; + r.right += m.right; + r.top -= m.top; + r.bottom += m.bottom; + r.top -= GetStdFontCy() + 4; + return r; +} + +void TopWindowFrame::SetClient(Rect r) +{ + SetRect(ComputeClient(r)); +} + +Point TopWindowFrame::GetDragMode(Point p) +{ + Size sz = GetSize(); + Rect m = ChMargins(FBImg::border()); + Point dir; + dir.y = p.y < m.top ? -1 : p.y > sz.cy - m.top ? 1 : 0; + dir.x = p.x < m.left ? -1 : p.x > sz.cx - m.right ? 1 : 0; + return dir; +} + +void TopWindowFrame::StartDrag() +{ + if(maximized) + return; + if(!sizeable && (dir.x || dir.y)) + return; + SetCapture(); + startrect = GetRect(); + startpos = GetMousePos(); + LLOG("START DRAG ---------------"); +} + +void TopWindowFrame::GripResize() +{ + dir = Point(1, 1); + StartDrag(); +} + +void TopWindowFrame::LeftDown(Point p, dword keyflags) +{ + dir = GetDragMode(p); + StartDrag(); +} + +void TopWindowFrame::CancelMode() +{ + holding = false; +} + +void TopWindowFrame::LeftUp(Point p, dword keyflags) +{ + holding = false; +} + +void TopWindowFrame::Hold() +{ + if(HasCapture()) { + if(HasMouse() && GetMouseLeft() && holding) + StartDrag(); + ReleaseCapture(); + holding = false; + } +} + +void TopWindowFrame::LeftHold(Point p, dword keyflags) +{ +/* if(HasCapture() || FullWindowDrag) + return; + dir = GetDragMode(p); + if(!dir.x && !dir.y) + StartDrag();*/ +} + +void TopWindowFrame::LeftDouble(Point p, dword keyflags) +{ + ToggleMaximize(); + IgnoreMouseUp(); +} + +void TopWindowFrame::MouseMove(Point, dword) +{ + LDUMP(HasWndCapture()); + LDUMP(HasCapture()); + if(!HasCapture() || holding) + return; + Size msz = ComputeClient(minsize).GetSize(); + Point p = GetMousePos() - startpos; + Rect r = startrect; + if(dir.x == -1) + r.left = min(r.left + p.x, startrect.right - msz.cx); + if(dir.x == 1) + r.right = max(r.right + p.x, startrect.left + msz.cx); + if(dir.y == -1) + r.top = min(r.top + p.y, startrect.bottom - msz.cy); + if(dir.y == 1) + r.bottom = max(r.bottom + p.y, startrect.top + msz.cy); + if(dir.y == 0 && dir.x == 0) + r.Offset(p); + SetRect(r); +} + +Image TopWindowFrame::GetDragImage(Point dir) +{ + static Image (*im[9])() = { + Image::SizeTopLeft, Image::SizeLeft, Image::SizeBottomLeft, + Image::SizeTop, Image::Arrow, Image::SizeBottom, + Image::SizeTopRight, Image::SizeRight, Image::SizeBottomRight, + }; + return (*im[(dir.x + 1) * 3 + (dir.y + 1)])(); +} + +Image TopWindowFrame::CursorImage(Point p, dword) +{ + if(!sizeable) + return Image::Arrow(); + return GetDragImage(HasCapture() ? dir : GetDragMode(p)); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/Turtle.brc b/rainbow/Turtle/Turtle.brc new file mode 100644 index 000000000..e5c5409ae --- /dev/null +++ b/rainbow/Turtle/Turtle.brc @@ -0,0 +1 @@ +BINARY(turtle_html, "Turtle.html") diff --git a/rainbow/Turtle/Turtle.h b/rainbow/Turtle/Turtle.h new file mode 100644 index 000000000..9763fa9dc --- /dev/null +++ b/rainbow/Turtle/Turtle.h @@ -0,0 +1,131 @@ +#define GUI_TURTLE + +#define _TODO_ // _DBG_ + +#include + +#ifdef PLATFORM_POSIX +#include +#endif + +NAMESPACE_UPP + +#define IMAGECLASS FBImg +#define IMAGEFILE +#include + +class SystemDraw : public SDraw { +public: + virtual void PutImage(Point p, const Image& img, const Rect& src); + virtual void PutRect(const Rect& r, Color color); + +public: + enum Code { + RECT = 0, + IMAGE = 1, + SETIMAGE = 2, + INVERTRECT = 3, + STD_CURSORIMAGE = 4, + SETCURSORIMAGE = 5, + CURSORIMAGE = 6, + }; + + static Index img_index[3]; + + static int GetImageI(int from, Index& img_index, int maxcount, SystemDraw& w, const Image& img); + static int GetImageI(SystemDraw& w, const Image& img); + static void ResetI() { for(int i = 0; i < 3; i++) img_index[i].Clear(); } + + StringBuffer result; + + void Put8(int x) { result.Cat(x); } + void Put16(int x); + void Put32(int x); + void Put(Point p); + void Put(Size sz); + void Put(const Rect& r); + void Put(const String& s); + + bool CanSetSurface() { return false; } + static void Flush() {} +}; + +struct BackDraw__ : public SystemDraw { + BackDraw__() : SystemDraw() {} +}; + +class BackDraw : public BackDraw__ { // Dummy only, as we are running in GlobalBackBuffer mode + Size size; + Draw *painting; + Point painting_offset; + ImageBuffer ib; + +public: + virtual bool IsPaintingOp(const Rect& r) const; + +public: + void Put(SystemDraw& w, int x, int y) {} + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy) {} + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy() {} + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SImageDraw { +public: + ImageDraw(Size sz) : SImageDraw(sz) {} + ImageDraw(int cx, int cy) : SImageDraw(cx, cy) {} +}; + +void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, uint64 pattern); + +class TopWindowFrame; + +#define GUIPLATFORM_CTRL_TOP_DECLS Ctrl *owner_window; + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE + +#define GUIPLATFORM_PASTECLIP_DECLS \ + bool dnd; \ + friend struct DnDLoop; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE + +class PrinterJob { // Dummy only... + NilDraw nil; + Vector pages; + +public: + Draw& GetDraw() { return nil; } + operator Draw&() { return GetDraw(); } + const Vector& GetPages() const { return pages; } + int operator[](int i) const { return 0; } + int GetPageCount() const { return 0; } + + bool Execute() { return false; } + + PrinterJob& Landscape(bool b = true) { return *this; } + PrinterJob& MinMaxPage(int minpage, int maxpage) { return *this; } + PrinterJob& PageCount(int n) { return *this; } + PrinterJob& CurrentPage(int currentpage) { return *this; } + PrinterJob& Name(const char *_name) { return *this; } + + PrinterJob(const char *name = NULL) {} + ~PrinterJob() {} +}; + +void USDLSetup(dword flags); + + +void InitTelpp(); + +END_UPP_NAMESPACE + +#define GUIPLATFORM_INCLUDE_AFTER diff --git a/rainbow/Turtle/Turtle.html b/rainbow/Turtle/Turtle.html new file mode 100644 index 000000000..261ece198 --- /dev/null +++ b/rainbow/Turtle/Turtle.html @@ -0,0 +1,293 @@ + + + + + + + + + + +Your browser does not support the HTML5 canvas tag. + + + + + diff --git a/rainbow/Turtle/Turtle.upp b/rainbow/Turtle/Turtle.upp new file mode 100644 index 000000000..6294fce3b --- /dev/null +++ b/rainbow/Turtle/Turtle.upp @@ -0,0 +1,30 @@ +description "HTML5 backend\377"; + +uses + Painter, + CtrlLib; + +file + Turtle.h, + Keys.h, + After.h, + Local.h, + Draw.cpp, + Image.cpp, + FB.iml, + Ctrl.h, + DrawDragRect.cpp, + Ctrl.cpp, + Wnd.cpp, + Cursor.cpp, + Socket.cpp, + Event.cpp, + Top.h, + TopFrame.cpp, + Top.cpp, + Clip.cpp, + DnD.cpp, + ChSysInit.cpp, + Turtle.brc, + Turtle.html; + diff --git a/rainbow/Turtle/Wnd.cpp b/rainbow/Turtle/Wnd.cpp new file mode 100644 index 000000000..f19fa321d --- /dev/null +++ b/rainbow/Turtle/Wnd.cpp @@ -0,0 +1,459 @@ +#include "Local.h" + +#ifdef GUI_TURTLE + +NAMESPACE_UPP + +#define LLOG(x) LOG(x) +#define LDUMP(x) //DDUMP(x) +#define LDUMPC(x) //DDUMPC(x) +#define LTIMING(x) RTIMING(x) + +Ptr Ctrl::desktop; +Vector Ctrl::topctrl; + +bool Ctrl::invalid; + +bool Ctrl::sdlMouseIsIn; + +Point Ctrl::fbCursorPos = Null; +Image Ctrl::fbCursorImage; +Rect Ctrl::fbCaretRect; +int Ctrl::fbCaretTm; +bool Ctrl::fbEndSession; +int Ctrl::PaintLock; + +bool Ctrl::SystemCursor; + +void Ctrl::SetDesktop(Ctrl& q) +{ + desktop = &q; + desktop->SetOpen(true); + desktop->NewTop(); + invalid = true; +} + +void Ctrl::EndSession() +{ + GuiLock __; + LLOG("Ctrl::EndSession"); + fbEndSession = true; + EndSessionLoopNo = EventLoopNo; +} + +void Ctrl::Exit() +{ + TopWindow::ShutdownWindows(); + Ctrl::CloseTopCtrls(); + _TODO_ +} + +void Ctrl::SetDesktopSize(Size sz) +{ + if(desktop) + desktop->SetRect(sz); + invalid = true; + SyncTopWindows(); +} + +int Ctrl::FindTopCtrl() const +{ + for(int i = 0; i < topctrl.GetCount(); i++) + if(this == topctrl[i]) + return i; + return -1; +} + +bool Ctrl::IsAlphaSupported() +{ + return false; +} + +bool Ctrl::IsCompositedGui() +{ + return false; +} + +Vector Ctrl::GetTopCtrls() +{ + Vector ctrl; + if(desktop) + ctrl.Add(desktop); + for(int i = 0; i < topctrl.GetCount(); i++) + if(!dynamic_cast(topctrl[i])) + ctrl.Add(topctrl[i]); + return ctrl; +} + +Ctrl *Ctrl::GetOwner() +{ + GuiLock __; + int q = FindTopCtrl(); + if(q > 0 && topctrl[q]->top) { + Ctrl *x = topctrl[q]->top->owner_window; + LDUMP(Upp::Name(x)); + return dynamic_cast(x) ? x->GetOwner() : x; + } + return NULL; +} + +Ctrl *Ctrl::GetActiveCtrl() +{ + GuiLock __; + return focusCtrl ? focusCtrl->GetTopCtrl() : NULL; +} + +// Vector Ctrl::hotkey; + +int Ctrl::RegisterSystemHotKey(dword key, Callback cb) +{ +/* ASSERT(key >= K_DELTA); + int q = hotkey.GetCount(); + for(int i = 0; i < hotkey.GetCount(); i++) + if(!hotkey[i]) { + q = i; + break; + } + hotkey.At(q) = cb; + dword mod = 0; + if(key & K_ALT) + mod |= MOD_ALT; + if(key & K_SHIFT) + mod |= MOD_SHIFT; + if(key & K_CTRL) + mod |= MOD_CONTROL; + + return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/ + return -1; +} + +void Ctrl::UnregisterSystemHotKey(int id) +{ +/* if(id >= 0 && id < hotkey.GetCount()) { + UnregisterHotKey(NULL, id); + hotkey[id].Clear(); + }*/ +} + +void Ctrl::SyncTopWindows() +{ + for(int i = 0; i < topctrl.GetCount(); i++) { + TopWindow *w = dynamic_cast(topctrl[i]); + if(w) + w->SyncRect(); + } +} + +/* +ViewDraw::ViewDraw(Ctrl *ctrl) +{ + if(Ctrl::invalid) + Ctrl::DoPaint(); + Ctrl::invalid = false; + Ctrl::RemoveCursor(); + Ctrl::RemoveCaret(); + Rect r = ctrl->GetScreenView(); + Ctrl::invalid.Add(r); + Ctrl::AddUpdate(r); + for(int i = max(ctrl->GetTopCtrl()->FindTopCtrl() + 1, 0); i < Ctrl::topctrl.GetCount(); i++) { + Rect rr = Ctrl::topctrl[i]->GetScreenRect(); + ExcludeClip(rr); + Subtract(Ctrl::invalid, rr); + } + Offset(r.TopLeft()); +} + +ViewDraw::~ViewDraw() +{ + Ctrl::DoUpdate(); +} +*/ + +Rect Ctrl::GetClipBound(const Vector& inv, const Rect& r) +{ + Rect ri = Null; + for(int j = 0; j < inv.GetCount(); j++) { + Rect rr = inv[j] & r; + if(!rr.IsEmpty()) + ri = IsNull(ri) ? rr : rr | ri; + } + return ri; +} + +void Ctrl::WndUpdate(const Rect&) +{ + GuiLock __; + Invalidate(); + DoPaint(); +} + +Rect Ctrl::GetWndScreenRect() const +{ + GuiLock __; + return GetRect(); +} + +void Ctrl::WndShow(bool b) +{ + GuiLock __; +} + +void Ctrl::WndUpdate() +{ + GuiLock __; +} + +bool Ctrl::IsWndOpen() const { + GuiLock __; + return FindTopCtrl() >= 0 || this == desktop; +} + +void Ctrl::SetAlpha(byte alpha) +{ + GuiLock __; +} + +Rect Ctrl::GetWorkArea() const +{ + GuiLock __; + return GetVirtualScreenArea(); +} + +void Ctrl::GetWorkArea(Array& rc) +{ + GuiLock __; + Array r; + r.Add(GetVirtualScreenArea()); +} + +Rect Ctrl::GetVirtualWorkArea() +{ + return GetVirtualScreenArea(); +} + +Rect Ctrl::GetWorkArea(Point pt) +{ + return GetVirtualScreenArea(); +} + +Rect Ctrl::GetVirtualScreenArea() +{ + GuiLock __; + return desktop ? desktop->GetRect() : Rect(0, 0, 0, 0); +} + +Rect Ctrl::GetPrimaryWorkArea() +{ + return GetVirtualScreenArea(); +} + +Rect Ctrl::GetPrimaryScreenArea() +{ + return GetVirtualScreenArea(); +} + +int Ctrl::GetKbdDelay() +{ + GuiLock __; + return 500; +} + +int Ctrl::GetKbdSpeed() +{ + GuiLock __; + return 1000 / 32; +} + +void Ctrl::DestroyWnd() +{ + for(int i = 0; i < topctrl.GetCount(); i++) + if(topctrl[i]->top && topctrl[i]->top->owner_window == this) + topctrl[i]->WndDestroy(); + int q = FindTopCtrl(); + if(q >= 0) { + Invalidate(); + topctrl.Remove(q); + } + if(top) { + delete top; + top = NULL; + } + isopen = false; + TopWindow *win = dynamic_cast(this); + if(win) + win->DestroyFrame(); +} + +void Ctrl::WndDestroy() +{ + DestroyWnd(); + if(topctrl.GetCount()) + topctrl.Top()->ActivateWnd(); +} + +void Ctrl::PutForeground() +{ + int q = FindTopCtrl(); + if(q >= 0) { + Invalidate(); + topctrl.Remove(q); + topctrl.Add(this); + } + Vector< Ptr > fw; + for(int i = 0; i < topctrl.GetCount(); i++) + if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this) + fw.Add(topctrl[i]); + for(int i = 0; i < fw.GetCount(); i++) + if(fw[i]) + fw[i]->PutForeground(); +} + +void Ctrl::SetWndForeground() +{ + GuiLock __; + ASSERT(IsOpen()); + if(IsWndForeground()) + return; + Ctrl *to = this; + while(to->top && to->top->owner_window) + to = to->top->owner_window; + to->PutForeground(); + if(this != focusCtrl) + ActivateWnd(); +} + +bool Ctrl::IsWndForeground() const +{ + GuiLock __; + bool b = false; + for(int i = 0; i < topctrl.GetCount(); i++) { + const TopWindow *tw = dynamic_cast(topctrl[i]); + if(tw) + b = tw == this; + } + return b; +} + +void Ctrl::WndEnable(bool) +{ + GuiLock __; +} + +bool Ctrl::SetWndFocus() +{ + GuiLock __; + return true; +} + +bool Ctrl::HasWndFocus() const +{ + GuiLock __; + return focusCtrl && focusCtrl->GetTopCtrl() == this; +} + +bool Ctrl::SetWndCapture() +{ + GuiLock __; + ASSERT(IsMainThread()); + return true; +} + +bool Ctrl::ReleaseWndCapture() +{ + GuiLock __; + ASSERT(IsMainThread()); + return true; +} + +bool Ctrl::HasWndCapture() const +{ + GuiLock __; + return captureCtrl && captureCtrl->GetTopCtrl() == this; +} + +void Ctrl::WndInvalidateRect(const Rect&) +{ + GuiLock __; + Invalidate(); +} + +void Ctrl::WndSetPos(const Rect& rect) +{ + GuiLock __; + TopWindow *w = dynamic_cast(this); + if(w) + w->SyncFrameRect(rect); + Invalidate(); + SetWndRect(rect); +} + +void Ctrl::WndScrollView(const Rect& r, int dx, int dy) +{ + GuiLock __; + LLOG("ScrollView " << rect); + WndInvalidateRect(r); +} + +void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost) +{ + ASSERT(!IsChild() && !IsOpen() && FindTopCtrl() < 0); + NewTop(); + if(owner) { + Ctrl *owner_window = owner->GetTopWindow(); + if(!owner_window) + owner_window = owner->GetTopCtrl(); + ASSERT(owner_window->IsOpen()); + if(owner_window != desktop) { + owner_window->SetForeground(); + top->owner_window = owner_window; + } + } + topctrl.Add(this); + popup = isopen = true; + RefreshLayoutDeep(); + if(activate) SetFocusWnd(); + Invalidate(); +} + +Rect Ctrl::GetDefaultWindowRect() { + GuiLock __; + static int ii = 0; + Rect rect = GetVirtualScreenArea(); + Size sz = rect.GetSize(); + rect.Deflate(sz / 10); + rect.Offset(Size(GetStdFontCy(), 2 * GetStdFontCy()) * (++ii % 8)); + return rect; +} + +Vector SplitCmdLine__(const char *cmd) +{ + Vector out; + while(*cmd) + if((byte)*cmd <= ' ') + cmd++; + else if(*cmd == '\"') { + WString quoted; + while(*++cmd && (*cmd != '\"' || *++cmd == '\"')) + quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString()); + out.Add(quoted); + } + else { + const char *begin = cmd; + while((byte)*cmd > ' ') + cmd++; + out.Add(String(begin, cmd).ToWString()); + } + return out; +} + +void Ctrl::InstallPanicBox() +{ +} + +void Ctrl::SysEndLoop() +{ +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/Turtle/init b/rainbow/Turtle/init new file mode 100644 index 000000000..7d79b8f99 --- /dev/null +++ b/rainbow/Turtle/init @@ -0,0 +1,5 @@ +#ifndef _Turtle_icpp_init_stub +#define _Turtle_icpp_init_stub +#include "Painter/init" +#include "CtrlLib/init" +#endif diff --git a/rainbow/WebWord/WebWord.upp b/rainbow/WebWord/WebWord.upp index 41a942c9d..e62f9cb0b 100644 --- a/rainbow/WebWord/WebWord.upp +++ b/rainbow/WebWord/WebWord.upp @@ -2,11 +2,13 @@ uses Core, Telpp, plugin/DroidFonts, - RichEdit; + RichEdit, + Turtle, + PdfDraw; file WebWord.cpp; mainconfig - "" = "SSE2 TELPP RAINBOW"; + "" = "SSE2 TURTLE RAINBOW"; diff --git a/rainbow/WebWord/init b/rainbow/WebWord/init index f79b75263..a679bad6a 100644 --- a/rainbow/WebWord/init +++ b/rainbow/WebWord/init @@ -4,4 +4,6 @@ #include "Telpp/init" #include "plugin/DroidFonts/init" #include "RichEdit/init" +#include "Turtle/init" +#include "PdfDraw/init" #endif diff --git a/rainbow/guiplatform.h b/rainbow/guiplatform.h index b34419d64..f36d0e43a 100644 --- a/rainbow/guiplatform.h +++ b/rainbow/guiplatform.h @@ -52,3 +52,9 @@ //need to make SDL_keysym.h known before K_ enum #define GUIPLATFORM_INCLUDE #endif + +#ifdef flagTURTLE +#define GUIPLATFORM_KEYCODES_INCLUDE +//need to make SDL_keysym.h known before K_ enum +#define GUIPLATFORM_INCLUDE +#endif