Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
UppHub
Status & Roadmap
FAQ
Authors & License
Forums
Funding U++
Search on this site











SourceForge.net Logo

SourceForge.net Logo

GitHub Logo

Discord Logo

Framebuffer

 

Generic framebuffer GUI rainbow

 

 

Top.h

 

//$ 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();

//$ };

 

 

 

Gui.h

 

#define GUI_FB

 

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<Cloff> {

        Point org;

        HRGN  hrgn;

        Rect  drawingclip;

    };

 

    Array<Cloff> 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 <ShellAPI.h>

 

#endif

#endif

 

#define GUIPLATFORM_INCLUDE_AFTER "Win32GuiA.h"

 

 

 

Framebuffer.h

 

#define GUI_FB

 

#include <Painter/Painter.h>

 

NAMESPACE_UPP

 

#define IMAGECLASS FBImg

#define IMAGEFILE <Framebuffer/FB.iml>

#include <Draw/iml_header.h>

 

class SystemDraw : public BufferPainter {

public:

    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 IsPaintingOp(const Rect& r) const;

 

private:

    Vector<Point> offset;

    

    void Push();

    void Pop();

 

public:

    Point   GetOffset() const;

    bool    CanSetSurface()                         { return false; }

    bool    Clip(const Rect& r)                     { return Draw::Clip(r); }

    bool    Clip(int x, int y, int cx, int cy)      { return Draw::Clip(x, y, cx, cy); }

    

    static void Flush()                                        {}

 

    SystemDraw();

    ~SystemDraw();

};

 

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();

};

 

struct ImageDraw__ {

    ImageBuffer    image;

    ImageBuffer    alpha;

    

    ImageDraw__(int cx, int cy) : image(cx, cy), alpha(cx, cy) {}

};

 

class ImageDraw : private ImageDraw__, public BufferPainter {

    BufferPainter  alpha_painter;

    bool           has_alpha;

 

    Image Get(bool pm) const;

 

public:

    Draw& Alpha();

 

    operator Image() const               { return Get(true); }

    

    Image GetStraight() const            { return Get(false); }

    

    ImageDraw(Size sz);

    ImageDraw(int cx, int 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 <Framebuffer/Ctrl.h>

 

#define GUIPLATFORM_PASTECLIP_DECLS \

    bool dnd; \

    friend struct DnDLoop; \

 

#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Framebuffer/Top.h>

 

// to be implemented by final FB {

 

bool FBIsWaitingEvent();

bool FBProcessEvent(bool *quit);

void FBSleep(int ms);

void FBInitUpdate();

void FBUpdate(const Rect& area);

void FBFlush();

void FBQuitSession();

 

// }

 

class PrinterJob { // Dummy only...

    NilDraw             nil;

    Vector<int>         pages;

 

public:

    Draw&               GetDraw()                       { return nil; }

    operator            Draw&()                         { return GetDraw(); }

    const Vector<int>&  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()                                       {}

};

 

END_UPP_NAMESPACE

 

#define GUIPLATFORM_INCLUDE_AFTER <Framebuffer/After.h>

 

 

 

After.h

 

class ViewDraw : public SystemDraw {

public:

    ViewDraw(Ctrl *ctrl);

    ~ViewDraw();

};

 

 

/*

class ViewDraw : public SystemDraw {

    Vector<Rect> dummy;

public:

    ViewDraw(Ctrl *) : SystemDraw(Ctrl::framebuffer, dummy) { dummy.Add(Rect(10, 10, 100, 100)); }

};

*/

class DHCtrl : Ctrl {};

 

#include FRAMEBUFFER_INCLUDE

 

 

 

Fb.h

 

#ifndef _Framebuffer_Fb_h_

#define _Framebuffer_Fb_h_

 

#include <CtrlLib/CtrlLib.h>

 

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

 

 

 

Ctrl.h

 

//$ class Ctrl {

private:

    static Ptr<Ctrl>      desktop;

    static Vector<Ctrl *> topctrl;

    static ImageBuffer    framebuffer;

    static Vector<Rect>   invalid, update;

 

    static Point fbCursorPos;

    static Image fbCursorImage;

    

    static Point fbCursorBakPos;

    static Image fbCursorBak;

    

    static Rect  fbCaretRect;

    static Image fbCaretBak;

    static int   fbCaretTm;

    

    static int   renderingMode;

    

    static bool  fbEndSession;

    static int64 fbEventLoop;

    static int64 fbEndSessionLoop;

 

    static Image GetBak(Rect& tr);

    static void RemoveCursor();

    static void RemoveCaret();

    static void CursorSync();

    

    int FindTopCtrl() const;

    static Rect GetClipBound(const Vector<Rect>& inv, const Rect& r);

    static void DoPaint();

    static void DoUpdate();

    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<Ctrl> t, int event, Point p, int zdelta);

    Vector<Rect> GetPaintRects();

 

    static void DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz,

                         const byte *pattern, int animation);

    static void DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n,

                              const byte *pattern, int animation);

 

    friend struct PaintProxy__;

    friend class TopWindowFrame;

    friend class SystemDraw;

    friend struct DnDLoop;

 

    void  SetOpen(bool b)               { isopen = b; }

 

protected:

    static int PaintLock;

 

public:

    static void DoMouseFB(int event, Point p, int zdelta = 0);

    static bool DoKeyFB(dword key, int cnt);

 

    static void InitFB();

    static void ExitFB();

    static void EndSession();

 

    static void  SetDesktop(Ctrl& q);

    static Ctrl *GetDesktop()                  { return desktop; }

    static void  SetFramebufferSize(Size sz);

    

    static const ImageBuffer& GetFrameBuffer() { return framebuffer; }

    

    static void SetRenderingMode(int mode);

 

    static void AddUpdate(const Rect& rect);

 

    void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,

                      Color color, int type, int animation);

 

    static Ctrl *FindMouseTopCtrl();

 

    static bool FullWindowDrag;

    

    enum { DRAWDRAGRECT_SCREEN = 0x8000 };

 

//$ };

 

 

 

Event.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LLOG(x) //DLOG(x)

#define LDUMP(x) //DDUMP(x)

 

static Point fbmousepos;

 

Point GetMousePos() {

    return fbmousepos;

}

 

void Ctrl::MouseEventFB(Ptr<Ctrl> t, int event, Point p, int zdelta)

{

    if(!t->IsEnabled())

        return;

    Rect rr = t->GetRect();

    if((event & Ctrl::ACTION) == DOWN) {

        Ptr<Ctrl> q = t;

        TopWindowFrame *wf = dynamic_cast<TopWindowFrame *>(~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(fbmousepos))

            return t->IsEnabled() ? t : NULL;

    }

    return desktop->IsEnabled() ? desktop : NULL;

}

 

void Ctrl::DoMouseFB(int event, Point p, int zdelta)

{

    fbmousepos = p;

    int a = event & Ctrl::ACTION;

    if(a == Ctrl::UP && Ctrl::ignoreclick) {

        EndIgnore();

        return;

    }

    else

    if(a == Ctrl::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<Ctrl> 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();

    }

}

 

bool Ctrl::DoKeyFB(dword key, int cnt)

{

    bool b = DispatchKey(key, cnt);

    SyncCaret();

    Ctrl *desktop = GetDesktop();

    if(desktop)

        desktop->PostInput();

    return b;

}

 

Image Ctrl::GetBak(Rect& tr)

{

    Image bak;

    tr.Intersect(framebuffer.GetSize());

    if(!tr.IsEmpty()) {

        Image h = framebuffer;

        bak = CreateImage(tr.GetSize(), Black);

        Copy(bak, Point(0, 0), h, tr);

        framebuffer = h;

    }

    return bak;

}

 

void Ctrl::RemoveCursor()

{

    if(!IsNull(fbCursorBakPos)) {

        Copy(framebuffer, fbCursorBakPos, fbCursorBak, fbCursorBak.GetSize());

        AddUpdate(Rect(fbCursorBakPos, fbCursorBak.GetSize()));

    }

    fbCursorPos = fbCursorBakPos = Null;

    fbCursorBak = Null;

}

 

void Ctrl::RemoveCaret()

{

    if(!IsNull(fbCaretRect)) {

        Copy(framebuffer, fbCaretRect.TopLeft(), fbCaretBak, fbCaretBak.GetSize());

        AddUpdate(fbCaretRect);

    }

    fbCaretRect = Null;

    fbCaretBak = 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()

{

    GuiLock __;

}

 

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();

    LDUMP(GetTickCount());

    if(fbCursorPos != p || cr != fbCaretRect) {

        LDUMP(fbCaretRect);

        RemoveCursor();

        RemoveCaret();

 

        fbCursorPos = p;

        Size sz = fbCursorImage.GetSize();

        Rect tr(p, sz);

        fbCursorBak = GetBak(tr);

        fbCursorBakPos = tr.TopLeft();

 

        fbCaretRect = cr;

        if(!cr.IsEmpty()) {

            fbCaretBak = GetBak(cr);

            for(int y = cr.top; y < cr.bottom; y++) {

                RGBA *s = framebuffer[y] + cr.left;

                const RGBA *e = framebuffer[y] + cr.right;

                while(s < e) {

                    s->r = ~s->r;

                    s->g = ~s->g;

                    s->b = ~s->b;

                    s++;

                }

            }

            AddUpdate(fbCaretRect);

        }

 

        Over(framebuffer, p, fbCursorImage, sz);

        LLOG("Cursor: " << p << ", rect " << tr);

        AddUpdate(tr);

    }

}

 

void  Ctrl::SetMouseCursor(const Image& image)

{

    GuiLock __;

    if(image.GetSerialId() != fbCursorImage.GetSerialId()) {

        fbCursorImage = image;

        fbCursorPos = Null;

    }

}

 

END_UPP_NAMESPACE

 

#endif

 

 

Clip.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LLOG(x)  // LOG(x)

 

static VectorMap<String, ClipData> 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<String, ClipData>& data, const String& text)

{

    data.GetAdd("text", ClipData(text, sText));

    data.GetAdd("wtext", ClipData(text, sWText));

}

 

void Append(VectorMap<String, ClipData>& 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<Image>();

        q = s;

    }

    return q;

}

 

bool AcceptImage(PasteClip& clip)

{

    GuiLock __;

    return clip.Accept(ClipFmtsImage());

}

 

Image GetImage(PasteClip& clip)

{

    GuiLock __;

    Image m;

    if(Accept<Image>(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<Image&>(img));

}

 

String GetImageClip(const Image& img, const String& fmt)

{

    GuiLock __;

    if(img.IsEmpty()) return Null;

    if(fmt == ClipFmt<Image>())

        return sImage(img);

    return Null;

}

 

void AppendClipboardImage(const Image& img)

{

    GuiLock __;

    if(img.IsEmpty()) return;

    AppendClipboard(ClipFmt<Image>(), 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<String> GetFiles(PasteClip& clip)

{

    GuiLock __;

    Vector<String> f;

    return f;

}

 

END_UPP_NAMESPACE

 

#endif

 

 

 

Top.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

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()

{

    SyncCaption0();

}

 

void TopWindow::SyncTitle0()

{

    SyncCaption0();

}

 

void TopWindow::SyncCaption0()

{

    GuiLock __;

    frame->title = title.ToString();

    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)

{

    SyncCaption0();

}

 

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());

    SyncCaption0();

    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

 

 

 

Wnd.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LLOG(x)   //DLOG(x)

#define LDUMP(x)  //DDUMP(x)

#define LDUMPC(x) //DDUMPC(x)

 

ImageBuffer    Ctrl::framebuffer;

Vector<Rect>   Ctrl::invalid;

Vector<Rect>   Ctrl::update;

 

Ptr<Ctrl>      Ctrl::desktop;

Vector<Ctrl *> Ctrl::topctrl;

 

Point          Ctrl::fbCursorPos = Null;

Image          Ctrl::fbCursorImage;

Point          Ctrl::fbCursorBakPos = Null;

Image          Ctrl::fbCursorBak;

Rect           Ctrl::fbCaretRect;

Image          Ctrl::fbCaretBak;

int            Ctrl::fbCaretTm;

int            Ctrl::renderingMode = MODE_ANTIALIASED;

bool           Ctrl::fbEndSession;

bool           Ctrl::FullWindowDrag;

int            Ctrl::PaintLock;

 

void Ctrl::SetDesktop(Ctrl& q)

{

    desktop = &q;

    desktop->SetRect(framebuffer.GetSize());

    desktop->SetOpen(true);

    desktop->NewTop();

    invalid.Add(framebuffer.GetSize());

}

 

void Ctrl::SetRenderingMode(int mode)

{

    renderingMode = mode;

    invalid.Add(framebuffer.GetSize());

}

 

void Ctrl::InitFB()

{

    Ctrl::GlobalBackBuffer();

    Ctrl::InitTimer();

    framebuffer.Create(1, 1);

 

#ifdef PLATFORM_POSIX

    SetStdFont(ScreenSans(12)); //FIXME general handling

#endif

    ChStdSkin();

 

    static StaticRect x;

    x.Color(Cyan());

    SetDesktop(x);

}

 

void Ctrl::EndSession()

{

    GuiLock __;

    LLOG("Ctrl::EndSession");

    fbEndSession = true;

    EndSessionLoopNo = EventLoopNo;

}

 

void Ctrl::ExitFB()

{

    TopWindow::ShutdownWindows();

    Ctrl::CloseTopCtrls();

    if(fbEndSession)

        FBQuitSession();

}

 

void Ctrl::SetFramebufferSize(Size sz)

{

    framebuffer.Create(sz);

    if(desktop)

        desktop->SetRect(sz);

    invalid.Add(sz);

    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 *> Ctrl::GetTopCtrls()

{

    Vector<Ctrl *> ctrl;

    if(desktop)

        ctrl.Add(desktop);

    for(int i = 0; i < topctrl.GetCount(); i++)

        if(!dynamic_cast<TopWindowFrame *>(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<TopWindowFrame *>(x) ? x->GetOwner() : x;

    }

    return NULL;

}

 

Ctrl *Ctrl::GetActiveCtrl()

{

    GuiLock __;

    return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;

}

 

// Vector<Callback> 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();

    }*/

}

 

bool Ctrl::IsWaitingEvent()

{

    return FBIsWaitingEvent();

}

 

void Ctrl::AddUpdate(const Rect& rect)

{

    LLOG("@AddUpdate " << rect);

    AddRefreshRect(update, rect);

}

 

void Ctrl::AddInvalid(const Rect& rect)

{

    LLOG("@AddInvalid " << rect);

    AddRefreshRect(invalid, rect);

}

 

void Ctrl::SyncTopWindows()

{

    for(int i = 0; i < topctrl.GetCount(); i++) {

        TopWindow *w = dynamic_cast<TopWindow *>(topctrl[i]);

        if(w)

            w->SyncRect();

    }

}

 

bool Ctrl::ProcessEvent(bool *quit)

{

    LLOG("@ ProcessEvent");

    ASSERT(IsMainThread());

    if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle())

        ReleaseCtrlCapture();

    if(FBProcessEvent(quit)) {

        LLOG("FBProcesEvent returned true");

        SyncTopWindows();

        DefferedFocusSync();

        SyncCaret();

        return true;

    }

    return false;

}

 

Rect Ctrl::GetClipBound(const Vector<Rect>& 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;

}

 

 

ViewDraw::ViewDraw(Ctrl *ctrl)

{

    if(Ctrl::invalid.GetCount())

        Ctrl::DoPaint();

    Ctrl::invalid.Clear();

    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()

{

    FBInitUpdate();

    Ctrl::DoUpdate();

    FBFlush();

//    Ctrl::invalid.Clear();

}

 

void Ctrl::DoUpdate()

{

    LLOG("DoUpdate");

    invalid.Clear();

    CursorSync();

    LDUMPC(update);

#if 0

    FBUpdate(framebuffer.GetSize());

#else

    for(int i = 0; i < update.GetCount(); i++) {

        LDUMP(update[i]);

        FBUpdate(update[i]);

    }

#endif

    update.Clear();

//    Sleep(1000);

}

 

Vector<Rect> Ctrl::GetPaintRects()

{

    Vector<Rect> r;

    int q = FindTopCtrl();

    r.Add(GetScreenRect());

    for(int i = max(FindTopCtrl() + 1, 0); i < topctrl.GetCount(); i++)

        Subtract(r, topctrl[i]->GetScreenRect());

    return r;

}

 

 

void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count)

{

    while(count-- > 0) {

        byte p = pattern[7 & pos++];

        t->r ^= p;

        t->g ^= p;

        t->b ^= p;

        t += dir;

    }

}

 

void Ctrl::DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz, const byte *pattern, int animation)

{

    if(cx <= 0 || cy <= 0)

        return;

    Vector<Rect> rr = Intersection(clip, RectC(x, y, cx, cy));

    for(int i = 0; i < rr.GetCount(); i++) {

        Rect r = rr[i];

        AddUpdate(r);

        if(horz)

            for(int y = r.top; y < r.bottom; y++)

                DDRect(framebuffer[y] + r.left, 1, pattern, r.left + animation, r.GetWidth());

        else

            for(int x = r.left; x < r.right; x++)

                DDRect(framebuffer[r.top] + x, framebuffer.GetWidth(), pattern, r.top + animation, r.GetHeight());

    }

}

 

void Ctrl::DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n, const byte *pattern, int animation)

{

    int hn = min(rect.GetHeight(), n);

    int vn = min(rect.GetWidth(), n);

    DrawLine(clip, rect.left, rect.top, rect.GetWidth(), hn, true, pattern, animation);

    DrawLine(clip, rect.left, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);

    DrawLine(clip, rect.right - vn, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);

    DrawLine(clip, rect.left + vn, rect.bottom - hn, rect.GetWidth() - 2 * vn, hn, true, pattern, animation);

}

 

void Ctrl::DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,

                       Color color, int type, int animation)

{

    static byte solid[] =  { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

    static byte normal[] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 };

    static byte dashed[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };

    Point p = GetScreenView().TopLeft();

    Vector<Rect> pr;

    if(type & DRAWDRAGRECT_SCREEN) {

        pr.Add(Rect(framebuffer.GetSize()));

        type &= ~DRAWDRAGRECT_SCREEN;

        p = Point(0, 0);

    }

    else

        pr = Intersection(GetPaintRects(), clip.Offseted(p));

    const byte *pattern = type == DRAWDRAGRECT_DASHED ? dashed :

                          type == DRAWDRAGRECT_NORMAL ? normal : solid;

    RemoveCursor();

    RemoveCaret();

    DragRectDraw0(pr, rect1.Offseted(p), n, pattern, animation);

    DragRectDraw0(pr, rect2.Offseted(p), n, pattern, animation);

}

 

void Ctrl::DoPaint()

{

    LLOG("@ DoPaint");

    if(!PaintLock) {

        bool scroll = false;

        if(desktop)

            desktop->SyncScroll();

        for(int i = 0; i < topctrl.GetCount(); i++)

            topctrl[i]->SyncScroll();

        if((invalid.GetCount() || scroll) && desktop) {

            RemoveCursor();

            RemoveCaret();

            for(int phase = 0; phase < 2; phase++) {

                LLOG("DoPaint invalid phase " << phase);

                LDUMPC(invalid);

                SystemDraw painter;

                painter.Begin();

                for(int i = 0; i < invalid.GetCount(); i++) {

                    painter.RectPath(invalid[i]);

                    AddUpdate(invalid[i]);

                }

                painter.Painter::Clip();

                for(int i = topctrl.GetCount() - 1; i >= 0; i--) {

                    Rect r = topctrl[i]->GetRect();

                    Rect ri = GetClipBound(invalid, r);

                    if(!IsNull(ri)) {

                        painter.Clipoff(r);

                        topctrl[i]->UpdateArea(painter, ri - r.TopLeft());

                        painter.End();

                        Subtract(invalid, r);

                        painter.ExcludeClip(r);

                    }

                }

                Rect ri = GetClipBound(invalid, framebuffer.GetSize());

                if(!IsNull(ri))

                    desktop->UpdateArea(painter, ri);

            }

        }

    }

    DoUpdate();

}

 

void Ctrl::WndUpdate0r(const Rect& r)

{

    GuiLock __;

    Rect rr = r + GetRect().TopLeft();

    bool dummy;

    Vector<Rect> h;

    h <<= invalid;

    invalid = Intersect(invalid, rr, dummy);

    FBInitUpdate();

    DoPaint();

    invalid <<= h;

    Subtract(invalid, rr);

    FBFlush();

}

 

bool Ctrl::ProcessEvents(bool *quit)

{

    //LOGBLOCK("@ ProcessEvents");

//    MemoryCheckDebug();

    if(!ProcessEvent(quit))

        return false;

    while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop()));

    TimeStop tm;

    TimerProc(GetTickCount());

    LLOG("TimerProc elapsed: " << tm);

    SweepMkImageCache();

    FBInitUpdate();

    DoPaint();

    FBFlush();

    return true;

}

 

void Ctrl::EventLoop0(Ctrl *ctrl)

{

    GuiLock __;

    ASSERT(IsMainThread());

    ASSERT(LoopLevel == 0 || ctrl);

    LoopLevel++;

    LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);

    Ptr<Ctrl> 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);

        LDUMP(fbEndSessionLoop);

    }

 

    if(ctrl)

        LoopCtrl = ploop;

    LoopLevel--;

    LLOG(LOG_END << "Leaving event loop ");

}

 

void Ctrl::GuiSleep0(int ms)

{

    GuiLock __;

    ASSERT(IsMainThread());

    LLOG("GuiSleep");

    int level = LeaveGuiMutexAll();

    FBSleep(ms);

    EnterGuiMutex(level);

}

 

Rect Ctrl::GetWndScreenRect() const

{

    GuiLock __;

    return GetRect();

}

 

void Ctrl::WndShow0(bool b)

{

    GuiLock __;

}

 

void Ctrl::WndUpdate0()

{

    GuiLock __;

}

 

bool Ctrl::IsWndOpen() const {

    GuiLock __;

    return FindTopCtrl() >= 0 || this == desktop;

}

 

void Ctrl::SetAlpha(byte alpha)

{

    GuiLock __;

}

 

Rect Ctrl::GetWorkArea() const

{

    GuiLock __;

    return framebuffer.GetSize();

}

 

void Ctrl::GetWorkArea(Array<Rect>& rc)

{

    GuiLock __;

    Array<Rect> r;

    r.Add(framebuffer.GetSize());

}

 

Rect Ctrl::GetVirtualWorkArea()

{

    return framebuffer.GetSize();

}

 

Rect Ctrl::GetWorkArea(Point pt)

{

    return framebuffer.GetSize();

}

 

Rect Ctrl::GetVirtualScreenArea()

{

    GuiLock __;

    return framebuffer.GetSize();

}

 

Rect Ctrl::GetPrimaryWorkArea()

{

    Rect r;

    return framebuffer.GetSize();

}

 

Rect Ctrl::GetPrimaryScreenArea()

{

    return framebuffer.GetSize();

}

 

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]->WndDestroy0();

    int q = FindTopCtrl();

    if(q >= 0) {

        AddInvalid(GetRect());

        topctrl.Remove(q);

    }

    if(top) {

        delete top;

        top = NULL;

    }

    isopen = false;

    TopWindow *win = dynamic_cast<TopWindow *>(this);

    if(win)

        win->DestroyFrame();

}

 

void Ctrl::WndDestroy0()

{

    DestroyWnd();

    if(topctrl.GetCount())

        topctrl.Top()->ActivateWnd();

}

 

void Ctrl::PutForeground()

{

    int q = FindTopCtrl();

    if(q >= 0) {

        AddInvalid(GetRect());

        topctrl.Remove(q);

        topctrl.Add(this);

    }

    Vector< Ptr<Ctrl> > 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::SetWndForeground0()

{

    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<const TopWindow *>(topctrl[i]);

        if(tw)

            b = tw == this;

    }

    return b;

}

 

void Ctrl::WndEnable0(bool *b)

{

    GuiLock __;

    *b = true;

}

 

void Ctrl::SetWndFocus0(bool *b)

{

    GuiLock __;

    *b = 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& r)

{

    GuiLock __;

    int q = FindTopCtrl();

    if(q >= 0)

        AddInvalid(r + topctrl[q]->GetRect().TopLeft());

    else

        AddInvalid(r);

}

 

void Ctrl::WndSetPos0(const Rect& rect)

{

    GuiLock __;

    TopWindow *w = dynamic_cast<TopWindow *>(this);

    if(w)

        w->SyncFrameRect(rect);

    invalid.Add(GetRect());

    SetWndRect(rect);

    invalid.Add(rect);

}

 

void  Ctrl::WndScrollView0(const Rect& r, int dx, int dy)

{

    GuiLock __;

    if(dx == 0 && dy == 0)

        return;

    if(dx && dy) {

        Refresh(r);

        return;

    }

    RemoveCursor();

    RemoveCaret();

    Rect sr = r.Offseted(GetScreenRect().TopLeft());

    Vector<Rect> pr = Intersection(GetPaintRects(), sr);

    for(int i = 0; i < pr.GetCount(); i++) {

        Rect r = pr[i];

        if(dx) {

            int n = r.GetWidth() - abs(dx);

            if(n > 0) {

                int to = r.left + dx * (dx > 0);

                int from = r.left - dx * (dx < 0);

                for(int y = r.top; y < r.bottom; y++)

                    memmove(framebuffer[y] + to, framebuffer[y] + from, n * sizeof(RGBA));

            }

            n = min(abs(dx), r.GetWidth());    

            Refresh(dx < 0 ? r.left : r.right - n, r.top, n, r.GetHeight());

        }

        else {

            int n = r.GetHeight() - abs(dy);

            for(int y = 0; y < n; y++)

                memmove(framebuffer[dy < 0 ? r.top + y : r.bottom - 1 - y] + r.left,

                        framebuffer[dy < 0 ? r.top + y - dy : r.bottom - 1 - y - dy] + r.left,

                        r.GetWidth() * sizeof(RGBA));

            n = min(abs(dy), r.GetHeight());    

            Refresh(r.left, dy < 0 ? r.bottom - n : r.top, r.GetWidth(), n);

        }

    }

 

    Vector<Rect> ur;

    for(int i = 0; i < invalid.GetCount(); i++)

        if(invalid[i].Intersects(sr))

            ur.Add(invalid[i]);

    for(int i = 0; i < ur.GetCount(); i++)

        AddInvalid(ur[i].Offseted(dx, dy));

}

 

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();

    AddInvalid(GetRect());

}

 

Rect Ctrl::GetDefaultWindowRect() {

    GuiLock __;

    static int ii = 0;

    Size sz = framebuffer.GetSize();

    Rect rect = framebuffer.GetSize();

    rect.Deflate(sz / 10);

    rect.Offset(Size(GetStdFontCy(), 2 * GetStdFontCy()) * (++ii % 8));

    return rect;

}

 

Vector<WString> SplitCmdLine__(const char *cmd)

{

    Vector<WString> 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;

}

 

END_UPP_NAMESPACE

 

#endif

 

 

 

TopFrame.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

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 = framebuffer.GetSize();

        if(GetRect().GetSize() != sz)

            SetRect(sz);

    }

}

 

void TopWindowFrame::Maximize()

{

    if(!maximized && maximize.IsShown()) {

        maximized = true;

        overlapped = GetRect();

        SetRect(framebuffer.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;

    if(FullWindowDrag) {

        SetCapture();

        startrect = GetRect();

        startpos = GetMousePos();

    }

    else {

        Rect r = GetScreenRect();

        RectTracker tr(*this);

        tr.SetCursorImage(GetDragImage(dir))

          .MaxRect(framebuffer.GetSize())

          .MinSize(ComputeClient(minsize).GetSize())

          .Pattern(DRAWDRAGRECT_DASHED | DRAWDRAGRECT_SCREEN)

          .Width(2)

          .Animation();

        PaintLock++;

        r = tr.Track(r, dir.x < 0 ? ALIGN_LEFT : dir.x > 0 ? ALIGN_RIGHT : ALIGN_CENTER,

                        dir.y < 0 ? ALIGN_TOP : dir.y > 0 ? ALIGN_BOTTOM : ALIGN_CENTER);

        PaintLock--;

        SetRect(r);

    }

    LLOG("START DRAG ---------------");

}

 

void TopWindowFrame::GripResize()

{

    dir = Point(1, 1);

    StartDrag();

}

 

void TopWindowFrame::LeftDown(Point p, dword keyflags)

{

    dir = GetDragMode(p);

    if(dir.x || dir.y || FullWindowDrag)

        StartDrag();

    else {

        SetCapture();

        holding = true;

        hold.Set(GetKbdDelay() / 3, THISBACK(Hold));

    }

}

 

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

 

 

 

Ctrl.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

#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 Ctrl::GetFrameBuffer()[y][x];

}

 

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;

}

 

void Ctrl::InstallPanicBox()

{

}

 

END_UPP_NAMESPACE

 

#endif

 

 

 

Draw.cpp

 

#include <CtrlCore/CtrlCore.h>

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LLOG(x) // LOG(x)

#define LTIMING(x) // RTIMING(x)

 

SystemDraw::SystemDraw()

:    BufferPainter(Ctrl::framebuffer, Ctrl::renderingMode)

{

}

 

SystemDraw::~SystemDraw()

{

}

 

 

void SystemDraw::Push()

{

    Point p = GetOffset();

    offset.Add(p);

    BufferPainter::BeginOp();

}

 

void SystemDraw::Pop()

{

    if(offset.GetCount())

        offset.Drop();

    BufferPainter::EndOp();

}

 

Point SystemDraw::GetOffset() const

{

    return offset.GetCount() ? offset.Top() : Point(0, 0);

}

 

void SystemDraw::BeginOp()

{

    Push();

}

 

void SystemDraw::EndOp()

{

    Pop();

}

 

void SystemDraw::OffsetOp(Point p)

{

    Push();

    offset.Top() += p;

    Translate(p.x, p.y);

}

 

bool SystemDraw::ClipOp(const Rect& r)

{

    Push();

    RectPath(r);

    Painter::Clip();

    return true;

}

 

bool SystemDraw::ClipoffOp(const Rect& r)

{

    Push();

    offset.Top() += r.TopLeft();

    RectPath(r);

    Painter::Clip();

    Translate(r.left, r.top);

    return true;

}

 

bool SystemDraw::IsPaintingOp(const Rect& r) const

{

    Rect rr = r + GetOffset();

    for(int i = 0; i < Ctrl::invalid.GetCount(); i++)

        if(Ctrl::invalid[i].Intersects(rr))

            return true;

    return true;

}

 

/*Rect SystemDraw::GetVirtualScreenArea()

{

    GuiLock __;

}*/

 

/*

void BackDraw::Destroy()

{

    GuiLock __;

}

 

void BackDraw::Create(SystemDraw& w, int cx, int cy) {

    GuiLock __;

}

 

void BackDraw::Put(SystemDraw& w, int x, int y) {

    GuiLock __;

}

*/

 

END_UPP_NAMESPACE

 

#endif

 

 

 

Image.cpp

 

#include <CtrlCore/CtrlCore.h>

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LTIMING(x) // RTIMING(x)

 

void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)

{

    GuiLock __;

}

 

void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff)

{

    GuiLock __;

}

 

Image ImageDraw::Get(bool pm) const

{

    ImageBuffer result(image.GetSize());

    const RGBA *e = image.End();

    const RGBA *p = ~image;

    RGBA *t = ~result;

    if(has_alpha) {

        const RGBA *a = ~alpha;

        while(p < e) {

            *t = *p++;

            (t++)->a = (a++)->r;

        }

        if(pm)

            Premultiply(result);

        result.SetKind(IMAGE_ALPHA);

    }

    else {

        while(p < e) {

            *t = *p++;

            (t++)->a = 255;

        }

    }

    return result;

}

 

Draw& ImageDraw::Alpha()

{

    has_alpha = true;

    return alpha_painter;

}

 

 

ImageDraw::ImageDraw(Size sz)

:    ImageDraw__(sz.cx, sz.cy),

    BufferPainter(image),

    alpha_painter(alpha)

{

    has_alpha = false;

}

 

ImageDraw::ImageDraw(int cx, int cy)

:    ImageDraw__(cx, cy),

    BufferPainter(image),

    alpha_painter(alpha)

{

    has_alpha = false;

}

 

#define IMAGECLASS FBImg

#define IMAGEFILE <Framebuffer/FB.iml>

#include <Draw/iml_source.h>

 

Image Image::Arrow() { return FBImg::arrow(); }

Image Image::Wait() { return FBImg::wait(); }

Image Image::IBeam() { return FBImg::ibeam(); }

Image Image::No() { return FBImg::no(); }

Image Image::SizeAll() { return FBImg::sizeall(); }

Image Image::SizeHorz() { return FBImg::sizehorz(); }

Image Image::SizeVert() { return FBImg::sizevert(); }

Image Image::SizeTopLeft() { return FBImg::sizetopleft(); }

Image Image::SizeTop() { return FBImg::sizetop(); }

Image Image::SizeTopRight() { return FBImg::sizetopright(); }

Image Image::SizeLeft() { return FBImg::sizeleft(); }

Image Image::SizeRight() { return FBImg::sizeright(); }

Image Image::SizeBottomLeft() { return FBImg::sizebottomleft(); }

Image Image::SizeBottom() { return FBImg::sizebottom(); }

Image Image::SizeBottomRight() { return FBImg::sizebottomright(); }

Image Image::Hand() { return FBImg::hand(); }

 

END_UPP_NAMESPACE

 

#endif

 

 

 

ChSysInit.cpp

 

#include <CtrlLib/CtrlLib.h>

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

void ChSysInit()

{

    CtrlImg::Reset();

    CtrlsImg::Reset();

    ChReset();

}

 

void ChHostSkin()

{

    ChSysInit();

}

 

END_UPP_NAMESPACE

 

#endif

 

 

 

DnD.cpp

 

#include "Fb.h"

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

#define LLOG(x)  // DLOG(x)

 

// --------------------------------------------------------------------------------------------

 

Ptr<Ctrl> sDnDSource;

 

Ctrl * Ctrl::GetDragAndDropSource()

{

    return sDnDSource;

}

 

struct DnDLoop : LocalLoop {

    const VectorMap<String, ClipData> *data;

    Vector<String> fmts;

 

    Image move, copy, reject;

    Ptr<Ctrl> 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> 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<Ctrl> 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<String, ClipData>& 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

 

 

 

Util.cpp

 

#include <CtrlCore/CtrlCore.h>

 

#ifdef GUI_FB

 

NAMESPACE_UPP

 

/*

static void sRenderLine(SystemDraw& w, int x, int y, int dx, int dy, int cx, int cy, int len, byte pattern)

{

    DLOG(len);

    for(int i = 0; i < len; i++)

        if((128 >> (i & 7)) & pattern)

            w.DrawRect(x + dx * i, y + dy * i, cx, cy, Black);

    DDUMP("~sRenderLine");

}

 

static void sRenderRect(SystemDraw& w, const Rect& r, int n, byte pattern)

{

    sRenderLine(w, r.left, r.top, 1, 0, 1, n, r.GetWidth(), pattern);

    sRenderLine(w, r.left, r.bottom - 1, 1, 0, 1, n, r.GetWidth(), pattern);

    sRenderLine(w, r.left, r.top, 0, 1, n, 1, r.GetHeight(), pattern);

    sRenderLine(w, r.right - 1, r.top, 0, 1, n, 1, r.GetHeight(), pattern);

}

 

void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2,

                 const Rect& clip, int n, Color color, uint64 pattern)

{

    DLOG("@ DrawDragRect " << rect1 << " " << rect2 << ", clip: " << clip << ", pattern: " << pattern);

    TIMING("DrawDrawRect");

    w.Clip(clip);

    w.Invert();

    sRenderRect(w, rect1, n, (byte)pattern);

    sRenderRect(w, rect2, n, (byte)pattern);

    Ctrl::AddUpdate((rect1 | rect2).Offseted(w.GetOffset()));

//    MemoryProfile mem;

//    DDUMP(mem);

    w.End();

}

 

 

 

 

static uint64 sGetAniPat(uint64 src, int pos)

{

    uint64 out = 0;

    pos &= 7;

    for(int i = 8; --i >= 0;) {

        byte sr = (byte)(src >> (8 * ((7 - i - pos) & 7)));

        out = (out << 8) | (byte)((sr | (sr << 8)) >> pos);

    }

    return out;

}

*/

 

 

/*

Size GetScreenSize()

{

    return ScreenInfo().GetPageSize();

}

*/

 

void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,

                 Color color, int type, int animation)

{

    q.DragRectDraw(rect1, rect2, clip, n, color, type, animation);

}

 

END_UPP_NAMESPACE

 

#endif

 

 

 

 

Do you want to contribute?