uppsrc: gtk3 replaces gtk2 as default linux backend

git-svn-id: svn://ultimatepp.org/upp/trunk@13848 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2020-01-10 09:18:10 +00:00
parent 7b01bec9d1
commit b3fe362f4f
39 changed files with 1230 additions and 336 deletions

View file

@ -991,6 +991,7 @@ void Ctrl::ReSkin()
return;
lock++;
ChReset();
Csize.cx = Dsize.cx = IsNoLayoutZoom;
if(s_chdefault)
(*s_chdefault)();
if(skin)

View file

@ -2,6 +2,7 @@
#define CTRLCORE_H
#include <RichText/RichText.h>
#include <Painter/Painter.h>
#ifdef flagNOGTK
#undef flagGTK

View file

@ -8,10 +8,6 @@ uses
library(WIN32 !MSC8ARM) "advapi32 comdlg32 comctl32";
library((LINUX | BSD) & !NOGTK & !RAINBOW & !GTK3 & GUI & !OSX) "gtk-x11-2.0 gdk-x11-2.0 atk-1.0 gdk_pixbuf-2.0 m pangocairo-1.0 fontconfig Xext Xrender Xinerama Xi Xrandr Xcursor Xfixes pango-1.0 cairo X11 gobject-2.0 gmodule-2.0 glib-2.0";
library((LINUX | BSD) & GTK3) "gtk-3.0 gdk-3.0 atk-1.0 gdk_3.0 m pangocairo-1.0 fontconfig Xext Xrender Xinerama Xi Xrandr Xcursor Xfixes pango-1.0 cairo X11 gobject-2.0 gmodule-2.0 glib-2.0";
library(WIN32 !MSC8ARM) "user32 gdi32";
library(LINUX !RAINBOW GUI) "X11 Xrender Xinerama";
@ -34,6 +30,8 @@ library(DRAGONFLY) "Xext Xinerama";
link(OSX !X11) "-framework Foundation -framework Cocoa -framework Carbon";
pkg_config(POSIX !X11) gtk+-3.0;
file
Core readonly separator,
CtrlCore.h options(BUILDER_OPTION) PCH,
@ -102,6 +100,7 @@ file
X11DHCtrl.cpp,
X11Event.i,
Gtk readonly separator,
gtk3-todo.txt,
Gtk.h,
GtkAfter.h,
GtkKeys.h,

View file

@ -353,6 +353,7 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
GuiLock __;
LEVELCHECK(w, this);
LTIMING("CtrlPaint");
LLOG("=== CtrlPaint " << UPP::Name(this) << ", clip: " << clip << ", rect: " << GetRect() << ", view: " << GetView());
Rect rect = GetRect().GetSize();
Rect orect = rect.Inflated(overpaint);
if(!IsShown() || orect.IsEmpty() || clip.IsEmpty() || !clip.Intersects(orect))
@ -417,7 +418,7 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
Rect ocl = cl - off;
if(ocl.Intersects(Rect(qr.GetSize()).Inflated(overpaint))) {
w.Offset(off);
q->CtrlPaint(w, cl - off);
q->CtrlPaint(w, ocl);
w.End();
}
}
@ -596,7 +597,7 @@ void Ctrl::UpdateArea0(SystemDraw& draw, const Rect& clip, int backpaint)
{
GuiLock __;
LTIMING("UpdateArea");
LLOG("========== UPDATE AREA " << UPP::Name(this) << " " << clip << " ==========");
LLOG("========== UPDATE AREA " << UPP::Name(this) << ", clip: " << clip << " ==========");
ExcludeDHCtrls(draw, GetRect().GetSize(), clip);
if(globalbackbuffer) {
CtrlPaint(draw, clip);

View file

@ -2,29 +2,16 @@
#define PLATFORM_X11 // To keep legacy code happy
#ifdef GDK_KEY_Delete
#define GDKEY(x) GDK_KEY_##x
#else
#define GDKEY(x) GDK_##x
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
@ -69,10 +56,9 @@ private:
void Pop();
Vector<Point> offset;
Vector<Rect> clip;
Vector<Rect> invalid; // for IsPainting checks, if empty, only clip extents is checked
cairo_t *cr;
GdkDrawable *drawable;
GdkRegion *invalid;
struct TextGlyph : Moveable<TextGlyph> {
int x;
@ -100,12 +86,13 @@ public:
void SetColor(Color c);
operator cairo_t*() { return cr; }
void SetInvalid(GdkRegion *r) { invalid = r; }
void PickInvalid(Vector<Rect>&& inv) { invalid = pick(inv); }
Point GetOffset() const;
bool CanSetSurface() { return true; }
static void Flush() {} // TODO?
SystemDraw(cairo_t *cr, GdkDrawable *dw/* = NULL*/) : cr(cr), drawable(dw) { (void)drawable; invalid = NULL; }
// SystemDraw(cairo_t *cr, GdkDrawable *dw/* = NULL*/) : cr(cr), drawable(dw) { (void)drawable; invalid = NULL; }
SystemDraw(cairo_t *cr) : cr(cr) {}
~SystemDraw();
};

View file

@ -57,11 +57,13 @@ void Ctrl::PanicMsgBox(const char *title, const char *text)
__BREAK__;
}
int Ctrl::scale;
void InitGtkApp(int argc, char **argv, const char **envptr)
{
LLOG(rmsecs() << " InitGtkApp");
#ifdef _MULTITHREADED
#if !GLIB_CHECK_VERSION(2, 32, 0)
#if !GTK_CHECK_VERSION(2, 32, 0)
if(!g_thread_supported())
g_thread_init(NULL);
#endif
@ -70,6 +72,14 @@ void InitGtkApp(int argc, char **argv, const char **envptr)
EnterGuiMutex();
#endif
gtk_init(&argc, &argv);
Ctrl::SetUHDEnabled(true);
Ctrl::scale = 1;
#if GTK_CHECK_VERSION(3, 10, 0)
Ctrl::scale = gdk_window_get_scale_factor(gdk_screen_get_root_window(gdk_screen_get_default()));
#endif
Ctrl::GlobalBackBuffer();
Ctrl::ReSkin();
g_timeout_add(20, (GSourceFunc) Ctrl::TimeHandler, NULL);

View file

@ -9,10 +9,51 @@ namespace Upp {
Ptr<Ctrl> Ctrl::grabwindow;
Ptr<Ctrl> Ctrl::grabpopup;
#if GTK_CHECK_VERSION(3, 20, 0)
GdkSeat *Ctrl::GetSeat()
{
return gdk_display_get_default_seat(gdk_display_get_default());
}
#endif
GdkDevice *Ctrl::GetMouseDevice()
{
#if GTK_CHECK_VERSION(3, 20, 0)
return gdk_seat_get_pointer(GetSeat());
#else
return gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default()));
#endif
}
bool Ctrl::MouseIsGrabbed()
{
return gdk_display_device_is_grabbed(gdk_display_get_default(), GetMouseDevice());
}
bool Ctrl::GrabMouse()
{
return
#if GTK_CHECK_VERSION(3, 20, 0)
gdk_seat_grab(GetSeat(), gdk(), GDK_SEAT_CAPABILITY_ALL_POINTING, true, NULL, NULL, NULL, 0)
#else
gdk_device_grab(GetMouseDevice(), gdk(), GDK_OWNERSHIP_APPLICATION, true, (GdkEventMask)0, NULL, GDK_CURRENT_TIME)
#endif
== GDK_GRAB_SUCCESS;
}
void Ctrl::UngrabMouse()
{
#if GTK_CHECK_VERSION(3, 20, 0)
gdk_seat_ungrab(GetSeat());
#else
gdk_device_ungrab(GetMouseDevice(), GDK_CURRENT_TIME);
#endif
}
void Ctrl::StopGrabPopup()
{
if(grabpopup && gdk_pointer_is_grabbed()) {
gdk_pointer_ungrab(CurrentTime);
if(grabpopup && MouseIsGrabbed()) {
UngrabMouse();
grabpopup = NULL;
}
}
@ -23,13 +64,7 @@ void Ctrl::StartGrabPopup()
Ctrl *w = activePopup[0];
if(w && w->IsOpen()) {
ReleaseWndCapture0();
static GdkCursor *NormalArrowCursor;
ONCELOCK {
NormalArrowCursor = gdk_cursor_new(GDK_LEFT_PTR);
}
if(gdk_pointer_grab(w->gdk(), FALSE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK),
NULL, NormalArrowCursor, CurrentTime) == GDK_GRAB_SUCCESS)
if(w->GrabMouse())
grabpopup = w;
}
}
@ -44,9 +79,7 @@ bool Ctrl::SetWndCapture()
return false;
StopGrabPopup();
ReleaseWndCapture();
if(gdk_pointer_grab(gdk(), FALSE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK),
NULL, NULL, CurrentTime) == GDK_GRAB_SUCCESS) {
if(GrabMouse()) {
grabwindow = this;
return true;
}
@ -59,7 +92,7 @@ bool Ctrl::ReleaseWndCapture0()
ASSERT(IsMainThread());
LLOG("ReleaseWndCapture");
if(grabwindow) {
gdk_pointer_ungrab(CurrentTime);
UngrabMouse();
grabwindow = NULL;
StartGrabPopup();
return true;
@ -75,20 +108,15 @@ bool Ctrl::ReleaseWndCapture()
bool Ctrl::HasWndCapture() const
{
GuiLock __;
return this == grabwindow && grabwindow->IsOpen() && gdk_pointer_is_grabbed();
return this == grabwindow && grabwindow->IsOpen() && MouseIsGrabbed();
}
void Ctrl::CaptureSync()
{
if(grabwindow && grabwindow->IsOpen() && !gdk_pointer_is_grabbed()) {
if(gdk_pointer_grab(grabwindow->gdk(), FALSE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK),
NULL, NULL, CurrentTime) != GDK_GRAB_SUCCESS) {
grabwindow = NULL;
}
}
if(grabwindow && grabwindow->IsOpen() && !MouseIsGrabbed() && !grabwindow->GrabMouse())
grabwindow = NULL;
}
}
};
#endif
#endif

View file

@ -26,12 +26,12 @@ void Ctrl::Create(Ctrl *owner, bool popup)
w.id = top->id;
w.ctrl = this;
w.gtk = top->window;
w.gdk = top->window->window;
w.gdk = gtk_widget_get_window(top->window);
TopWindow *tw = dynamic_cast<TopWindow *>(this);
if(popup && !owner) {
gtk_window_set_decorated(gtk(), FALSE);
gtk_window_set_has_frame(gtk(), FALSE);
// gtk_window_set_has_frame(gtk(), FALSE);
gtk_window_set_type_hint(gtk(), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
}
else
@ -44,18 +44,21 @@ void Ctrl::Create(Ctrl *owner, bool popup)
gtk_widget_set_events(top->window, 0xffffffff);
g_signal_connect(top->window, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
g_signal_connect(top->window, "draw", G_CALLBACK(GtkDraw), (gpointer)(uintptr_t)top->id);
GdkWindowTypeHint hint = gtk_window_get_type_hint(gtk());
if(tw && findarg(hint, GDK_WINDOW_TYPE_HINT_NORMAL, GDK_WINDOW_TYPE_HINT_DIALOG, GDK_WINDOW_TYPE_HINT_UTILITY) >= 0)
tw->SyncSizeHints();
Rect r = GetRect();
gtk_window_move(gtk(), r.left, r.top);
gtk_window_resize(gtk(), r.GetWidth(), r.GetHeight());
gtk_window_set_default_size (gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
gtk_window_move(gtk(), LSC(r.left), LSC(r.top));
gtk_window_resize(gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
gtk_widget_realize(top->window);
if(owner && owner->top)
gtk_window_set_transient_for(gtk(), owner->gtk());
gtk_widget_set_app_paintable(top->window, TRUE);
@ -81,9 +84,8 @@ void Ctrl::Create(Ctrl *owner, bool popup)
activeCtrl = this;
int mousex, mousey;
gdk_window_get_pointer(gdk(), &mousex, &mousey, NULL);
Point m(mousex, mousey);
GdkModifierType mod;
Point m = GetMouseInfo(gdk(), mod);
r = GetWndScreenRect().GetSize();
if(r.Contains(m))
DispatchMouse(MOUSEMOVE, m);

View file

@ -42,7 +42,7 @@ void GuiPlatformGripResize(TopWindow *q)
if(q->IsOpen()) {
Point p = GetMousePos();
gtk_window_begin_resize_drag(q->gtk(), GDK_WINDOW_EDGE_SOUTH_EAST,
1, p.x, p.y, Ctrl::CurrentTime);
1, Ctrl::LSC(p.x), Ctrl::LSC(p.y), Ctrl::CurrentTime);
}
}

View file

@ -26,6 +26,18 @@ _DBG_
static void CaptureSync();
static gboolean GtkEvent(GtkWidget *widget, GdkEvent *key, gpointer user_data);
static gboolean GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer data);
static Point GetMouseInfo(GdkWindow *win, GdkModifierType& mod);
static GdkDevice *GetMouseDevice();
#if GTK_CHECK_VERSION(3, 20, 0)
static GdkSeat *GetSeat();
#endif
static bool MouseIsGrabbed();
bool GrabMouse();
static void UngrabMouse();
static int scale; // in case GUI is scaling (e.g. in UHD mode)
enum {
EVENT_NONE = -15321,
@ -65,6 +77,7 @@ _DBG_
void Proc();
bool SweepConfigure(bool wait);
bool SweepFocus(bool wait);
void SyncWndRect(const Rect& rect);
static BiVector<GEvent> Events;
static Vector< Ptr<Ctrl> > activePopup; // created with 'activate' flag - usually menu
@ -75,7 +88,7 @@ _DBG_
static Ptr<Ctrl> grabwindow;
static Ptr<Ctrl> grabpopup;
static Ptr<Ctrl> sel_ctrl;
static Ptr<Ctrl> activeCtrl; // this is used to hold focus when popup is destroyed
static Ptr<Ctrl> activeCtrl;
static int FindId(int id);
static int FindCtrl(Ctrl *ctrl);
@ -170,6 +183,10 @@ public: // really private:
static Vector<dword> keyhot;
static Vector<dword> modhot;
static guint MouseState;
static int SCL(int x) { return scale * x; }
static Rect SCL(int x, int y, int cx, int cy) { return RectC(SCL(x), SCL(y), SCL(cx), SCL(cy)); }
static double LSC(int x) { return (double)x / scale; }
public:
static void EndSession() {}
@ -181,7 +198,7 @@ public:
static guint32 CurrentTime;
static GEvent CurrentEvent;
GdkWindow *gdk() const { return top ? top->window->window : NULL; }
GdkWindow *gdk() const { return top ? gtk_widget_get_window(top->window) : NULL; }
GtkWindow *gtk() const { return top ? (GtkWindow *)top->window : NULL; }
static GdkFilterReturn RootKeyFilter(GdkXEvent *xevent, GdkEvent *event, gpointer data);

View file

@ -22,7 +22,7 @@ Ctrl *Ctrl::GetDragAndDropSource()
void Ctrl::GtkDragBegin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
if(IsNull(dnd_icon))
gtk_drag_set_icon_default(context);
gtk_drag_set_icon_default(context);
else {
ImageGdk m(dnd_icon);
gtk_drag_set_icon_pixbuf(context, m, 0, 0);
@ -114,16 +114,16 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
dnd_icon = Null;
else {
Size sz = sample.GetSize();
if(sz.cx > 128)
sz.cx = 128;
if(sz.cy > 128)
sz.cy = 128;
int maxsize = DPI(128);
if(sz.cx > maxsize)
sz.cx = maxsize;
if(sz.cy > maxsize)
sz.cy = maxsize;
sz += 2;
ImageDraw iw(sz);
iw.DrawRect(sz, White());
DrawFrame(iw, sz, Black());
iw.DrawImage(1, 1, sz.cx, sz.cy, sample);
ImageBuffer b(128, 128);
dnd_icon = iw;
}
gtk_drag_begin(w->top->window, list, GdkDragAction(gdk_actions),
@ -287,7 +287,7 @@ PasteClip Ctrl::GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &mx, &my, &mod);
CurrentState = mod;
CurrentMousePos = Point(x, y) + w->GetScreenRect().TopLeft();
CurrentMousePos = Point(SCL(x), SCL(y)) + w->GetScreenRect().TopLeft();
w->DnD(CurrentMousePos, clip);
}
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE

View file

@ -119,7 +119,12 @@ bool SystemDraw::IsPaintingOp(const Rect& r) const
cr.Intersect(GetClip());
if(cr.IsEmpty())
return false;
return !invalid || gdk_region_rect_in(invalid, GdkRect(cr)) != GDK_OVERLAP_RECTANGLE_OUT;
if(invalid.GetCount() == 0)
return true;
for(const Rect& ir : invalid)
if(cr.Intersects(ir))
return true;
return false;
}
Rect SystemDraw::GetPaintRect() const
@ -134,21 +139,10 @@ void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
FlushText();
cairo_rectangle(cr, x, y, cx, cy);
if(color == InvertColor()) {
#if GTK_CHECK_VERSION(2,24,0) && (CAIRO_VERSION_MAJOR > 1 || CAIRO_VERSION_MINOR > 9)
SetColor(White());
cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
cairo_fill(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
#else
if(drawable) {
GdkGC *gc = gdk_gc_new(drawable);
gdk_gc_set_function(gc, GDK_INVERT);
Point o = GetOffset();
gdk_draw_drawable(drawable, gc, drawable, x + o.x, y + o.y, x + o.x, y + o.y, cx, cy);
gdk_gc_set_function(gc, GDK_COPY);
gdk_gc_destroy(gc);
}
#endif
}
else {
SetColor(color);

View file

@ -4,8 +4,8 @@
namespace Upp {
#define LLOG(x) // DLOG(rmsecs() << ' ' << x)
//_DBG_ #define LOG_EVENTS
#define LLOG(x) // DLOG(rmsecs() << ' ' << x)
// #define LOG_EVENTS _DBG_
BiVector<Ctrl::GEvent> Ctrl::Events;
@ -28,7 +28,7 @@ Point GetMousePos() { return Ctrl::CurrentMousePos; }
Tuple2<int, const char *> xEvent[] = {
{ GDK_NOTHING, "GDK_NOTHING" },
{ GDK_DELETE, "GDK_DELETE" },
{ GDK_DESTROY, "GDK_DESTROY" },id
{ GDK_DESTROY, "GDK_DESTROY" },
{ GDK_EXPOSE, "GDK_EXPOSE" },
{ GDK_MOTION_NOTIFY, "GDK_MOTION_NOTIFY" },
{ GDK_BUTTON_PRESS, "GDK_BUTTON_PRESS" },
@ -57,7 +57,6 @@ Tuple2<int, const char *> xEvent[] = {
{ GDK_DROP_FINISHED, "GDK_DROP_FINISHED" },
{ GDK_CLIENT_EVENT, "GDK_CLIENT_EVENT" },
{ GDK_VISIBILITY_NOTIFY, "GDK_VISIBILITY_NOTIFY" },
{ GDK_NO_EXPOSE, "GDK_NO_EXPOSE" },
{ GDK_SCROLL, "GDK_SCROLL" },
{ GDK_WINDOW_STATE, "GDK_WINDOW_STATE" },
{ GDK_SETTING, "GDK_SETTING" },
@ -79,6 +78,42 @@ Ctrl *Ctrl::GetTopCtrlFromId(int id)
return NULL;
}
gboolean Ctrl::GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
GuiLock __;
Ctrl *p = GetTopCtrlFromId(user_data);
if(p) {
p->fullrefresh = false;
cairo_scale(cr, 1.0 / scale, 1.0 / scale);
p->SyncWndRect(p->GetWndScreenRect()); // avoid black areas when resizing
SystemDraw w(cr);
painting = true;
double x1, y1, x2, y2;
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
Rect r = RectC((int)x1, (int)y1, (int)ceil(x2 - x1), (int)ceil(y2 - y1));
w.Clip(r); // Because of IsPainting
cairo_rectangle_list_t *list = cairo_copy_clip_rectangle_list(cr);
if(list->status == CAIRO_STATUS_SUCCESS && list->num_rectangles < 10) {
Vector<Rect> clip;
for(int i = 0; i < list->num_rectangles; i++) {
const cairo_rectangle_t& r = list->rectangles[i];
clip.Add(Rect((int)r.x, (int)r.y, (int)(r.x + r.width), (int)(r.y + r.height)));
}
w.PickInvalid(pick(clip));
}
cairo_rectangle_list_destroy(list);
p->UpdateArea(w, r);
w.End();
if(p->top->dr)
DrawDragRect(*p, *p->top->dr);
painting = false;
}
return true;
}
gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
GuiLock __;
@ -96,34 +131,9 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
#endif
switch(event->type) {
case GDK_EXPOSE:
case GDK_DAMAGE:
if(p) {
#ifdef LOG_EVENTS
TimeStop tm;
#endif
p->fullrefresh = false;
GdkEventExpose *e = (GdkEventExpose *)event;
SystemDraw w(gdk_cairo_create(p->gdk()), p->gdk());
painting = true;
Rect r = RectC(e->area.x, e->area.y, e->area.width, e->area.height);
w.SetInvalid(e->region);
w.Clip(r);
p->UpdateArea(w, r);
w.End();
cairo_destroy(w);
if(p->top->dr)
DrawDragRect(*p, *p->top->dr);
painting = false;
#ifdef LOG_EVENTS
LOG("* " << ev << " elapsed " << tm);
#endif
}
return true;
case GDK_DELETE:
break;
case GDK_FOCUS_CHANGE:
LLOG("Focus Change " << GetSysTime());
if(p) {
if(((GdkEventFocus *)event)->in)
gtk_im_context_focus_in(p->top->im_context);
@ -152,7 +162,13 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
break;
case GDK_SCROLL: {
GdkEventScroll *e = (GdkEventScroll *)event;
value = findarg(e->direction, GDK_SCROLL_UP, GDK_SCROLL_LEFT) < 0 ? -120 : 120;
if(findarg(e->direction, GDK_SCROLL_UP, GDK_SCROLL_LEFT) >= 0)
value = 120;
else
if(findarg(e->direction, GDK_SCROLL_DOWN, GDK_SCROLL_RIGHT) >= 0)
value = -120;
else
return false;
break;
}
case GDK_KEY_PRESS:
@ -169,8 +185,7 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
case GDK_CONFIGURE: {
retval = false;
GdkEventConfigure *e = (GdkEventConfigure *)event;
value = RectC(e->x, e->y, e->width, e->height);
LLOG("GDK_CONFIGURE " << value);
value = SCL(e->x, e->y, e->width, e->height);
break;
}
default:
@ -232,6 +247,21 @@ void Ctrl::GEvent::operator=(const GEvent& e)
Set(e);
}
Point Ctrl::GetMouseInfo(GdkWindow *win, GdkModifierType& mod)
{
#if GTK_CHECK_VERSION(3, 20, 0)
GdkDisplay *display = gdk_window_get_display (win);
GdkDevice *pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
double x, y;
gdk_window_get_device_position_double (win, pointer, &x, &y, &mod);
return Point((int)SCL(x), (int)SCL(y));
#else
gint x, y;
gdk_window_get_pointer(win, &x, &y, &mod);
return Point(SCL(x), SCL(y));
#endif
}
void Ctrl::AddEvent(gpointer user_data, int type, const Value& value, GdkEvent *event)
{
if(Events.GetCount() > 50000)
@ -240,10 +270,8 @@ void Ctrl::AddEvent(gpointer user_data, int type, const Value& value, GdkEvent *
e.windowid = (uint32)(uintptr_t)user_data;
e.type = type;
e.value = value;
gint x, y;
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &x, &y, &mod);
e.mousepos = Point(x, y);
e.mousepos = GetMouseInfo(gdk_get_default_root_window(), mod);
e.state = (mod & ~(GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK)) | MouseState;
e.count = 1;
e.event = NULL;
@ -494,7 +522,6 @@ void Ctrl::Proc()
break;
}
case EVENT_FOCUS_CHANGE:
LLOG("FOCUS_CHANGE setting NULL");
activeCtrl = NULL;
break;
case GDK_DELETE: {
@ -507,16 +534,8 @@ void Ctrl::Proc()
}
return;
}
case GDK_CONFIGURE: {
Rect rect = CurrentEvent.value;
if(GetRect() != rect)
SetWndRect(rect);
{
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w && w->state == TopWindow::OVERLAPPED)
w->overlapped = rect;
}
}
case GDK_CONFIGURE:
SyncWndRect(CurrentEvent.value);
break;
default:
return;
@ -525,6 +544,14 @@ void Ctrl::Proc()
_this->PostInput();
}
void Ctrl::SyncWndRect(const Rect& rect)
{
if(GetRect() != rect)
SetWndRect(rect);
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w && w->state == TopWindow::OVERLAPPED)
w->overlapped = rect;
}
bool Ctrl::ProcessEvent0(bool *quit, bool fetch)
{

View file

@ -21,19 +21,21 @@ void TopWindow::SyncSizeHints()
return;
GdkGeometry m;
Size sz0 = GetRect().GetSize();
LLOG("SyncSizeHints sz0: " << sz0 << ", sizeable: " << sizeable << ", min: " << GetMinSize() << ", max: " << GetMaxSize());
Size sz = sz0;
if(sizeable)
sz = GetMinSize();
m.min_width = sz.cx;
m.min_height = sz.cy;
m.min_width = LSC(sz.cx);
m.min_height = LSC(sz.cy);
sz = sz0;
if(sizeable)
sz = GetMaxSize();
m.max_width = sz.cx;
m.max_height = sz.cy;
m.max_width = LSC(sz.cx);
m.max_height = LSC(sz.cy);
gtk_window_set_resizable(gtk(), sizeable);
gtk_window_set_geometry_hints(gtk(), top->window, &m,
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
gtk_widget_set_size_request(top->window, m.min_width, m.min_height);
}
void TopWindow::SyncTitle()
@ -136,10 +138,10 @@ void TopWindow::Open(Ctrl *owner)
GdkRectangle fr;
gdk_window_get_frame_extents(gdk(), &fr);
Rect r = GetRect();
frameMargins.left = max(frameMargins.left, minmax(r.left - fr.x, 0, 32));
frameMargins.right = max(frameMargins.right, minmax(fr.x + fr.width - r.right, 0, 32));
frameMargins.top = max(frameMargins.top, minmax(r.top - fr.y, 0, 64));
frameMargins.bottom = max(frameMargins.bottom, minmax(fr.y + fr.height - r.bottom, 0, 48));
frameMargins.left = max(frameMargins.left, minmax(r.left - SCL(fr.x), 0, 32));
frameMargins.right = max(frameMargins.right, minmax(SCL(fr.x + fr.width) - r.right, 0, 32));
frameMargins.top = max(frameMargins.top, minmax(r.top - SCL(fr.y), 0, 64));
frameMargins.bottom = max(frameMargins.bottom, minmax(SCL(fr.y + fr.height) - r.bottom, 0, 48));
}
void TopWindow::Open()
@ -214,7 +216,7 @@ void TopWindow::Overlap(bool effect)
TopWindow& TopWindow::TopMost(bool b, bool)
{
GuiLock __;
GuiLock __;
topmost = b;
SyncTopMost();
return *this;
@ -222,7 +224,7 @@ TopWindow& TopWindow::TopMost(bool b, bool)
bool TopWindow::IsTopMost() const
{
GuiLock __;
GuiLock __;
return topmost;
}

View file

@ -56,9 +56,7 @@ bool Ctrl::IsAlphaSupported()
bool Ctrl::IsCompositedGui()
{
GuiLock __;
static bool b = gdk_display_supports_composite(gdk_display_get_default());
return b;
return true; // limits some GUI effects that do not play well with advanced desktops
}
Vector<Ctrl *> Ctrl::GetTopCtrls()
@ -70,6 +68,8 @@ Vector<Ctrl *> Ctrl::GetTopCtrls()
return h;
}
cairo_surface_t *CreateCairoSurface(const Image& img);
void Ctrl::SetMouseCursor(const Image& image)
{
LLOG("SetMouseCursor");
@ -88,22 +88,31 @@ void Ctrl::SetMouseCursor(const Image& image)
int64 aux = image.GetAuxData();
GdkCursor *c = NULL;
if(aux)
c = gdk_cursor_new((GdkCursorType)(aux - 1));
c = gdk_cursor_new_for_display(gdk_display_get_default(), (GdkCursorType)(aux - 1));
else
if(IsNull(image))
c = gdk_cursor_new(GDK_BLANK_CURSOR);
c = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_BLANK_CURSOR);
else {
Point p = image.GetHotSpot();
#if GTK_CHECK_VERSION(3, 10, 0)
cairo_surface_t *surface = CreateCairoSurface(image);
double scale = SCL(1);
cairo_surface_set_device_scale(surface, scale, scale);
c = gdk_cursor_new_from_surface(gdk_display_get_default(), surface, p.x / scale, p.y / scale);
cairo_surface_destroy(surface);
#else
ImageGdk m;
m.Set(image);
GdkPixbuf *pb = m;
if(pb)
c = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pb, p.x, p.y);
#endif
}
if(c && topctrl->IsOpen()) {
gdk_window_set_cursor(topctrl->gdk(), c);
gdk_cursor_unref(c);
gdk_flush(); // Make it visible immediately
g_object_unref(c);
gdk_display_flush(gdk_display_get_default()); // Make it visible immediately
}
}
}
@ -191,14 +200,9 @@ Rect Ctrl::GetWndScreenRect() const
if(IsOpen()) {
gint x, y;
gdk_window_get_position(gdk(), &x, &y);
#if GTK_CHECK_VERSION(2, 24, 0)
gint width = gdk_window_get_width(gdk());
gint height = gdk_window_get_height(gdk());
#else
gint width, height;
gdk_drawable_get_size(gdk(), &width, &height);
#endif
return RectC(x, y, width, height);
return SCL(x, y, width, height);
}
return Null;
}
@ -218,7 +222,7 @@ void Ctrl::WndShow(bool b)
bool Ctrl::IsWndOpen() const {
GuiLock __;
return top && top->window && top->window->window;
return top && top->window && gtk_widget_get_window(top->window);
}
void Ctrl::SetAlpha(byte alpha)
@ -243,6 +247,17 @@ Rect Ctrl::GetWorkArea() const
void Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
#if GTK_CHECK_VERSION(3, 22, 0)
GdkDisplay *s = gdk_display_get_default();
int n = gdk_display_get_n_monitors(s);
rc.Clear();
Vector<int> netwa;
for(int i = 0; i < n; i++) {
GdkRectangle rr;
gdk_monitor_get_workarea(gdk_display_get_monitor(s, i), &rr);
rc.Add(SCL(rr.x, rr.y, rr.width, rr.height));
}
#else
GdkScreen *s = gdk_screen_get_default();
int n = gdk_screen_get_n_monitors(s);
rc.Clear();
@ -250,22 +265,11 @@ void Ctrl::GetWorkArea(Array<Rect>& rc)
for(int i = 0; i < n; i++) {
GdkRectangle rr;
Rect r;
#if GTK_CHECK_VERSION (3, 3, 5) // U++ does not work with gtk3 yet, but be prepared
gdk_screen_get_monitor_workarea(s, i, &rr);
r = RectC(r.x, r.y, r.width, r.height);
#else
gdk_screen_get_monitor_geometry (s, i, &rr);
r = RectC(rr.x, rr.y, rr.width, rr.height);
#ifdef GDK_WINDOWING_X11
if(i == 0)
netwa = GetPropertyInts(gdk_screen_get_root_window(gdk_screen_get_default()),
"_NET_WORKAREA");
if(netwa.GetCount())
r = r & RectC(netwa[0], netwa[1], netwa[2], netwa[3]);
#endif
#endif
rc.Add(r);
}
#endif
}
Rect Ctrl::GetVirtualWorkArea()
@ -289,8 +293,8 @@ Rect Ctrl::GetVirtualScreenArea()
if(r.right == 0) {
gint x, y, width, height;
gdk_window_get_geometry(gdk_screen_get_root_window(gdk_screen_get_default()),
&x, &y, &width, &height, NULL);
r = RectC(x, y, width, height);
&x, &y, &width, &height);
r = SCL(x, y, width, height);
}
return r;
}
@ -298,18 +302,20 @@ Rect Ctrl::GetVirtualScreenArea()
Rect Ctrl::GetPrimaryWorkArea()
{
GuiLock __;
#if GTK_CHECK_VERSION(3, 22, 0)
GdkRectangle rr;
gdk_monitor_get_workarea(gdk_display_get_primary_monitor(gdk_display_get_default()), &rr);
return SCL(rr.x, rr.y, rr.width, rr.height);
#else
static Rect r;
if (r.right == 0) {
Array<Rect> rc;
GetWorkArea(rc);
#if GTK_CHECK_VERSION(2, 20, 0)
int primary = gdk_screen_get_primary_monitor(gdk_screen_get_default());
#else
int primary = 0;
#endif
primary >= 0 && primary < rc.GetCount() ? r = rc[primary] : r = GetVirtualScreenArea();
}
return r;
#endif
}
Rect Ctrl::GetPrimaryScreenArea()
@ -392,8 +398,17 @@ void Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
LLOG("WndInvalidateRect " << r);
gdk_window_invalidate_rect(gdk(), GdkRect(r), TRUE);
// gtk_widget_queue_draw_area(top->window, r.left, r.top, r.GetWidth(), r.GetHeight());
Rect rr;
if(scale > 1) {
rr.left = r.left / 2;
rr.top = r.top / 2;
rr.right = (r.right + 1) / 2;
rr.bottom = (r.bottom + 1) / 2;
}
else
rr = r;
gdk_window_invalidate_rect(gdk(), GdkRect(rr), TRUE);
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
@ -432,10 +447,11 @@ void Ctrl::WndSetPos(const Rect& rect)
SweepConfigure(false); // Remove any previous GDK_CONFIGURE for this window
if(!this_ || !IsOpen())
return;
Rect m(0, 0, 0, 0);
if(dynamic_cast<TopWindow *>(this))
m = GetFrameMargins();
gdk_window_move_resize(gdk(), rect.left - m.left, rect.top - m.top, rect.GetWidth(), rect.GetHeight());
gdk_window_move_resize(gdk(), LSC(rect.left - m.left), LSC(rect.top - m.top), LSC(rect.GetWidth()), LSC(rect.GetHeight()));
int t0 = msecs();
do { // Wait up to 500ms for corresponding GDK_CONFIGURE to arrive
if(SweepConfigure(true))
@ -465,9 +481,9 @@ void Ctrl::WndUpdate()
{
GuiLock __;
LLOG("WndUpdate0");
gdk_window_process_updates(gdk(), TRUE);
// gdk_window_process_updates(gdk(), TRUE); // deprecated
FetchEvents(FALSE); // Should pickup GDK_EXPOSE and repaint the window
gdk_flush();
gdk_display_flush(gdk_display_get_default());
}
Rect Ctrl::GetDefaultWindowRect()

View file

@ -27,7 +27,7 @@ XDisplay *Xdisplay()
Window Xroot()
{
return GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gdk_screen_get_default()));
return GDK_WINDOW_XID(gdk_screen_get_root_window(gdk_screen_get_default()));
}
String GetProperty(Window w, Atom property, Atom rtype)
@ -67,7 +67,7 @@ Atom XAtomRaw(const char *name)
Atom XAtom(const char *name)
{
GuiLock __;
GuiLock __;
Atom x;
INTERLOCKED {
static VectorMap<String, int> atoms;
@ -83,9 +83,9 @@ Atom XAtom(const char *name)
Vector<int> GetPropertyInts(GdkWindow *w, const char *property)
{
GuiLock __;
GuiLock __;
Vector<int> result;
String p = GetProperty(GDK_WINDOW_XWINDOW(w), XAtom(property), AnyPropertyType);
String p = GetProperty(GDK_WINDOW_XID(w), XAtom(property), AnyPropertyType);
const long int *ptr = (const long int *)~p;
const long int *lim = ptr + p.GetLength() / sizeof(long int);
result.Reserve(p.GetLength() / sizeof(long int));
@ -106,11 +106,13 @@ dword X11mods(dword key)
return mod;
}
#if 0 // retained for 3.8 compatibility
int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb)
{
GuiLock __;
ASSERT(key >= K_DELTA);
gdk_error_trap_push();
gdk_x11_display_error_trap_push(gdk_display_get_default());
KeyCode k = XKeysymToKeycode(Xdisplay(), key & 0xffff);
dword mod = X11mods(key);
bool r = false;
@ -120,7 +122,7 @@ int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb)
r = XGrabKey(Xdisplay(), k,
mod | (nlock * Mod2Mask) | (clock * LockMask) | (slock * Mod3Mask),
Xroot(), true, GrabModeAsync, GrabModeAsync) || r;
gdk_error_trap_pop();
gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default());
if(!r) return -1;
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
@ -138,18 +140,20 @@ void Ctrl::UnregisterSystemHotKey(int id)
{
GuiLock __;
if(id >= 0 && id < hotkey.GetCount() && hotkey[id]) {
gdk_error_trap_push();
gdk_x11_display_error_trap_push(gdk_display_get_default());
for(dword nlock = 0; nlock < 2; nlock++)
for(dword clock = 0; clock < 2; clock++)
for(dword slock = 0; slock < 2; slock++)
XUngrabKey(Xdisplay(), keyhot[id],
modhot[id] | (nlock * Mod2Mask) | (clock * LockMask) | (slock * Mod3Mask),
Xroot());
gdk_error_trap_pop();
gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default());
hotkey[id].Clear();
}
}
#endif
GdkFilterReturn Ctrl::RootKeyFilter(GdkXEvent *xevent, GdkEvent *Xevent, gpointer data)
{
XEvent *event = (XEvent *)xevent;

View file

@ -317,7 +317,6 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
ReSkin();
OleInitialize(NULL);
CoInitialize(NULL);
/* TRC 05/11/14: moved to GuiSleep to avoid thread creation in OCX DllMain
DWORD dummy;

View file

@ -0,0 +1,56 @@
- Issue with editfield text clipping in the right
- Remove warnings
- Test dark theme
- Test rect theme
- Blue Menta ugly scrollbars (round)
- TraditionalOk ugly scrollbars (centre image)
- DropChoice STDSIZE (.TopPosZ(10))
- LeftRoundness with DropChoice (DropChoiceRdO)
- 3.8 theme
- CleanTheme for X11
- libgtk-3-dev to buildrequires
- test DateTimeCtrl in dark mode
- check CtrlCore/Ctrl.tpp
- Check FileSel
NTH:
- spinbutton cosmetics
PROBABLY DONE:
- Problem with hot3 in scrollbar horizontal (check in SD)
DONE:
- Resizing delay
- Refresh issue
- Test & Fix filesel & fileselector
- Combobox push is weird
- right scrollbar
- Test grip resize
- toolbar button highlight
- correct checks in menu
- uword cannot be resized smaller
- Scrollbar margins (better fit for slider)
- Scrollbar Correct minsize, barsize...
- FileSelector
- Mint-Y disabled color is wrong
- Mint-Y tooltip color is wrong
- .iml cursors in UHD are wrong (e.g. header <-|->)
- cxZ Uword - wrong caret
- Combobox appearance issues (minor, round corners broken on the left)
- spinbuttons in UWord
- read-only dropchoice left color
- ColorPopup background
- Fix IsPainting
- Header synthetise
- Resizing fix black
- Slider thumb
- Remove DDUMPs
- TabBar synthetise
- Problem with theide menu
- LabelBox
- GtkStyleBool("has-backward-stepper")
- DropChoice read only active edge
- Scale must not be same as UHD
- makefile pkg-config support
- Test with 3.8

View file

@ -306,16 +306,25 @@ protected:
public:
struct Style : ChStyle<Style> {
Value item, topitem[3], topbar;
Color menutext, itemtext, topitemtext[3];
SeparatorCtrl::Style breaksep;
Value look, arealook;
Value popupframe, popupbody, popupiconbar;
Value item; // hot menu item background in popup menu
Value topitem[3]; // top menu item background normal/hot/pressed
Value topbar; // deprecated
Color menutext; // normal state popup menu item text
Color itemtext; // hot state popup menu item text
Color topitemtext[3]; // top menu item text normal/hot/pressed
SeparatorCtrl::Style breaksep; // separator between menu bars
Value look; // top menu background
Value arealook; // top menu backgroung if arealook and in frame (can be null, then 'look')
Value popupframe; // static frame of whole popup menu
Value popupbody; // background of whole popup menu
Value popupiconbar; // if there is special icon background in popup menu
SeparatorCtrl::Style separator;
Size maxiconsize;
int leftgap, textgap;
int lsepm, rsepm;
Point pullshift;
Size maxiconsize; // limit of icon size
int leftgap; // between left border and icon
int textgap;
int lsepm;
int rsepm;
Point pullshift; // offset of submenu popup
bool opaquetest; // If true, topmenu item can change hot text color
};

View file

@ -128,20 +128,278 @@ void RoundedRect(Painter& w, Rectf r, double rx, double ry, dword corner)
RoundedRect(w, r.left, r.top, r.GetWidth(), r.GetHeight(), rx, ry, corner);
}
Image MakeButton(int radius, const Image& face, int border_width, Color border_color, dword corner)
Image MakeElement(Size sz, double radius, const Image& face, int border_width, Color border_color, Event<Painter&, const Rectf&> shape)
{
int q = radius + border_width + 16;
Rectf r(0, 0, q, q);
Rectf r(0, 0, sz.cx, sz.cy);
ImagePainter w(r.GetSize());
w.Clear(RGBAZero());
RoundedRect(w, r.Deflated(border_width - 1), radius, radius, corner);
FillImage(w, r.Deflated(border_width - 1), face);
RoundedRect(w, r.Deflated(border_width / 2.0), radius, radius, corner);
w.Stroke(border_width, border_color);
Rectf dr = r.Deflated(border_width / 2.0);
if(!IsNull(face)) {
shape(w, dr);
FillImage(w, r.Deflated(border_width / 2.0 - 1), face);
}
shape(w, dr);
if(!IsNull(border_color))
w.Stroke(border_width, border_color);
Image m = w;
Point p1(radius, radius);
SetHotSpots(m, p1, (Point)r.BottomRight() - p1);
Point p1(radius + border_width, radius + border_width);
SetHotSpots(m, p1, (Point)r.BottomRight() - p1 - Point(1, 1));
return m;
}
Image MakeButton(int radius, const Image& face, int border_width, Color border_color, dword corner)
{
int q = radius + border_width + DPI(16);
return MakeElement(Size(q, q), radius, face, border_width, border_color, [&](Painter& w, const Rectf& r) {
RoundedRect(w, r, radius, radius, corner);
});
}
Image MakeButton(int radius, Color face, int border_width, Color border_color, dword corner)
{
return MakeButton(radius, CreateImage(Size(DPI(10), DPI(5)), face), border_width, border_color, corner);
}
Image Hot3(const Image& m)
{
Size sz = m.GetSize();
return WithHotSpots(m, sz.cx / 3, sz.cy / 3, sz.cx - sz.cx / 3, sz.cy - sz.cy / 3);
}
Image ChHot(const Image& m, int n)
{
return WithHotSpots(m, DPI(n), DPI(n), 0, 0);
}
Color AvgColor(const Image& m, const Rect& rr)
{
int r = 0;
int g = 0;
int b = 0;
int n = 0;
for(int y = rr.top; y < rr.bottom; y++)
for(int x = rr.left; x < rr.right; x++) {
RGBA c = m[y][x];
Unmultiply(&c, &c, 1);
if(c.a > 20) {
r += c.r;
g += c.g;
b += c.b;
n++;
}
}
return n ? Color(r / n, g / n, b / n) : SWhite();
}
Color AvgColor(const Image& m, int margin)
{
return AvgColor(m, Rect(m.GetSize()).Deflated(margin));
}
Color GetInk(const Image& m)
{
RGBA avg = AvgColor(m);
Color ink = SBlack();
int best = 0;
for(RGBA c : m) {
Unmultiply(&c, &c, 1);
if(c.a > 100) {
c.a = 255;
int q = Grayscale(abs(c.r - avg.r), abs(c.g - avg.g), abs(c.b - avg.b));
if(q > best) {
best = q;
ink = c;
}
}
}
return ink;
}
int GetRoundness(const Image& m)
{
Size isz = m.GetSize();
int bestd = 0, besth = 0;
int di = 0, hi = 0;
int hy = isz.cy / 2;
RGBA avg = AvgColor(m);
auto Chk = [&](int x, int y, int& best, int& besti) {
if(x < isz.cx && y < isz.cy) {
RGBA c = m[y][x];
Unmultiply(&c, &c, 1);
if(c.a > 100) {
int q = Grayscale(abs(c.r - avg.r), abs(c.g - avg.g), abs(c.b - avg.b));
if(q > best) {
best = q;
besti = x;
}
}
}
};
for(int i = 0; i < 8; i++) {
Chk(i, hy, besth, hi);
Chk(i, i, bestd, di);
}
return max(di - hi, 0);
}
static Value sSample;
void SetChameleonSample(const Value& m, bool once)
{
if(!once || IsNull(sSample))
sSample = m;
}
Value GetChameleonSample()
{
return sSample;
}
Image WithRect(Image m, int x, int y, int cx, int cy, Color c)
{
ImageBuffer ib(m);
for(int i = 0; i < cx; i++)
for(int j = 0; j < cy; j++)
ib[y + j][x + i] = c;
return ib;
}
Image WithLeftLine(const Image& m, Color c, int w)
{
return WithRect(m, 0, 0, w, m.GetHeight(), c);
}
Image WithRightLine(const Image& m, Color c, int w)
{
return WithRect(m, m.GetWidth() - w, 0, w, m.GetHeight(), c);
}
Image WithTopLine(const Image& m, Color c, int w)
{
return WithRect(m, 0, 0, m.GetWidth(), w, c);
}
Image WithBottomLine(const Image& m, Color c, int w)
{
return WithRect(m, 0, m.GetHeight() - w, m.GetWidth(), w, c);
}
void ChSynthetic(Image button100x100[4], Color text[4])
{
int roundness = DPI(3);
Color ink = SColorText();
for(int i = 0; i < 4; i++) {
Image m = button100x100[i];
if(i == 0) {
ink = GetInk(m);
roundness = GetRoundness(m) ? DPI(3) : 0;
CtrlsImg::Set(CtrlsImg::I_EFE, WithHotSpots(MakeButton(roundness, SColorPaper(), DPI(1), ink), DPI(3), DPI(1), 0, 0));
CtrlsImg::Set(CtrlsImg::I_VE, WithHotSpots(MakeButton(DPI(0), SColorPaper(), DPI(1), ink), DPI(2), DPI(2), 0, 0));
EditField::StyleDefault().Write().edge[CTRL_DISABLED] = WithHotSpots(MakeButton(roundness, SColorFace(), DPI(1), ink), DPI(3), DPI(1), 0, 0);
EditField::StyleDefault().Write().activeedge = true;
LabelBox::SetLook(WithHotSpots(MakeButton(2 * roundness / 3, Image(), DPI(1), ink), DPI(3), DPI(3), 0, 0));
}
Size sz = m.GetSize();
m = Crop(m, sz.cx / 8, sz.cy / 8, 6 * sz.cx / 8, 6 * sz.cy / 8);
{
auto Set = [&](Button::Style& s, const Image& arrow = Null) {
Value l = MakeButton(0, m, DPI(1), ink, 0);
s.look[i] = IsNull(l) ? l : ChLookWith(l, arrow);
};
Set(Button::StyleScroll().Write());
Set(Button::StyleEdge().Write());
Set(Button::StyleLeftEdge().Write());
ScrollBar::Style& s = ScrollBar::StyleDefault().Write();
Set(s.up, CtrlsImg::UA());
Set(s.down, CtrlsImg::DA());
Set(s.left, CtrlsImg::LA());
Set(s.right, CtrlsImg::RA());
}
{
MultiButton::Style& s = MultiButton::StyleDefault().Write();
s.clipedge = true;
s.border = s.trivialborder = 0;
s.left[i] = MakeButton(roundness, m, DPI(1), ink, CORNER_TOP_LEFT|CORNER_BOTTOM_LEFT);
s.trivial[i] = s.look[i] = s.right[i] = MakeButton(roundness, m, DPI(1), ink, CORNER_TOP_RIGHT|CORNER_BOTTOM_RIGHT);
auto Middle = [&](Image m) {
ImageBuffer ib(m);
for(int y = 0; y < DPI(1); y++)
for(int x = 0; x < ib.GetWidth(); x++) {
ib[y][x] = ink;
ib[ib.GetHeight() - y - 1][x] = ink;
}
return WithHotSpot(ib, DPI(1), DPI(1));
};
s.lmiddle[i] = Middle(WithRightLine(m, ink));
s.rmiddle[i] = Middle(WithLeftLine(m, ink));
s.monocolor[i] = s.fmonocolor[i] = text[i];
for(int i = 0; i < 4; i++)
s.edge[i] = EditField::StyleDefault().edge[i];
s.margin = Rect(DPI(3), 2, DPI(1), 2);
s.activeedge = true;
s.stdwidth = DPI(17);
}
{
SpinButtons::Style& sp = SpinButtons::StyleDefault().Write();
if(i == 0)
sp.dec = sp.inc = Button::StyleNormal();
auto Spin = [&](dword corners, const Image& sm) {
return ChLookWith(WithLeftLine(MakeButton(roundness, m, 0, Black(), corners), ink), sm, text[i]);
};
sp.inc.look[i] = Spin(CORNER_TOP_RIGHT, CtrlImg::spinup());
sp.dec.look[i] = Spin(CORNER_BOTTOM_RIGHT, CtrlImg::spindown());
sp.width = DPI(14); // DPI(17) - DPI(3) (droplist stdwidth minus frame)
}
{
HeaderCtrl::Style& hs = HeaderCtrl::StyleDefault().Write();
hs.look[i] = ChHot(WithBottomLine(WithRightLine(m, ink, 1), ink));
}
if(i == CTRL_DISABLED) {
ProgressIndicator::Style& s = ProgressIndicator::StyleDefault().Write();
s.hlook = MakeButton(roundness, m, DPI(1), ink);
s.hchunk = MakeButton(roundness, SColorHighlight(), DPI(1), ink);
s.bound = true;
s.nomargins = true;
}
if(i == CTRL_NORMAL || i == CTRL_PRESSED) {
Image sm = MakeElement(Size(DPI(10), DPI(20)), roundness, m, DPI(1), ink, [&](Painter& w, const Rectf& r) {
double cx = r.GetWidth();
double cy = r.GetHeight();
double uy = 0.4 * cy;
double uq = 0.5 * uy;
w.Move(r.left, r.top + cy)
.Line(r.left, r.top + uy)
.Quadratic(r.left, r.top + uq, r.left + cx / 2, r.top)
.Quadratic(r.left + cx, r.top + uq, r.left + cx, r.top + uy)
.Line(r.left + cx, r.top + cy)
.Close();
});
CtrlImg::Set(i == CTRL_PRESSED ? CtrlImg::I_hthumb1 : CtrlImg::I_hthumb, sm);
CtrlImg::Set(i == CTRL_PRESSED ? CtrlImg::I_vthumb1 : CtrlImg::I_vthumb, RotateClockwise(sm));
}
{
TabCtrl::Style& s = TabCtrl::StyleDefault().Write();
int adj = 8;
auto Face = [](int adj) {
Color c = SColorFace();
return Color(clamp(c.GetR() + adj, 0, 255),
clamp(c.GetG() + adj, 0, 255),
clamp(c.GetB() + adj, 0, 255));
};
s.body = MakeButton(0, Face(8), DPI(1), ink);
Image t = MakeButton(roundness, Face(decode(i, CTRL_NORMAL, -20,
CTRL_HOT, 2,
CTRL_PRESSED, 8,
-8)), DPI(1), ink, CORNER_TOP_LEFT|CORNER_TOP_RIGHT);
s.first[i] = s.last[i] = s.both[i] = s.normal[i] = ChHot(Crop(t, 0, 0, t.GetWidth(), t.GetHeight() - DPI(2)), DPI(3));
s.margin = 0;
s.sel = Rect(0, DPI(1), 0, DPI(1));
s.extendleft = DPI(2);
s.text_color[i] = SColorText();
}
}
}
}

View file

@ -11,4 +11,29 @@ enum {
void RoundedRect(Painter& w, double x, double y, double cx, double cy, double rx, double ry, dword corners);
void RoundedRect(Painter& w, Rectf r, double rx, double ry, dword corner);
Image MakeButton(int radius, const Image& face, int border_width, Color border_color, dword corner);
Image MakeElement(Size sz, double radius, const Image& face, int border_width, Color border_color, Event<Painter&, const Rectf&> shape);
Image MakeButton(int radius, const Image& face, int border_width, Color border_color = Null, dword corner = 0xff);
Image MakeButton(int radius, Color face, int border_width, Color border_color = Null, dword corner = 0xff);
Image Hot3(const Image& m); // Adds resizing hotspots at 1/3
Image ChHot(const Image& m, int n = 2); // Adds resizing hotspots DPI(n)
Color AvgColor(const Image& m, const Rect& rr);
Color AvgColor(const Image& m, int margin = 0);
Color GetInk(const Image& m); // the color that is most different from AvgColor
int GetRoundness(const Image& m);
Image WithRect(Image m, int x, int y, int cx, int cy, Color c);
Image WithLeftLine(const Image& m, Color c, int w = DPI(1));
Image WithRightLine(const Image& m, Color c, int w = DPI(1));
Image WithTopLine(const Image& m, Color c, int w = DPI(1));
Image WithBottomLine(const Image& m, Color c, int w = DPI(1));
// Creates synthetic style based on SColors and basic button face
void ChSynthetic(Image button100x100[4], Color text[4]);
// for diagnostics purposes
#ifdef _DEBUG
void SetChameleonSample(const Value& m, bool once = true);
Value GetChameleonSample();
#endif

View file

@ -4,12 +4,6 @@
namespace Upp {
Image Hot3(const Image& m)
{
Size sz = m.GetSize();
return WithHotSpots(m, sz.cx / 3, sz.cy / 3, sz.cx - sz.cx / 3, sz.cy - sz.cy / 3);
}
Image Coco_ThemeImage(Color bg, int cx, int cy, int margin, int type,
int value, int state, bool focus)
{
@ -26,29 +20,6 @@ Image Coco_ThemeImage(int cx, int cy, int margin, int type, int value, int state
Coco_ThemeImage(Black(), cx, cy, margin, type, value, state, focus)));
}
Color AvgColor(const Image& m, const Rect& rr)
{
int n = rr.GetWidth() * rr.GetHeight();
if(n <= 0)
return White();
int r = 0;
int g = 0;
int b = 0;
for(int y = rr.top; y < rr.bottom; y++)
for(int x = rr.left; x < rr.right; x++) {
RGBA c = m[y][x];
r += c.r;
g += c.g;
b += c.b;
}
return Color(r / n, g / n, b / n);
}
Color AvgColor(const Image& m, int margin = 0)
{
return AvgColor(m, Rect(m.GetSize()).Deflated(margin));
}
void ClampedAutoCrop(Image *h, int count)
{
AutoCrop(h, count);

View file

@ -1,6 +1,6 @@
#include "CtrlLib.h"
#ifdef PLATFORM_X11
#ifdef GUI_X11 // X11 uses GTK2 for look&feel
#ifndef flagNOGTK
#include "ChGtk.h"
@ -717,5 +717,18 @@ void ChHostSkin()
}
#else
namespace Upp {
void ChHostSkin() {}
Image GtkThemeIcon(const char *name, int rsz)
{
return CtrlImg::smallreporticon();
}
};
#endif
#endif

View file

@ -1,8 +1,6 @@
#include "CtrlLib.h"
#ifdef PLATFORM_X11
#ifdef GUI_X11
#ifdef flagNOGTK
namespace Upp {
@ -122,7 +120,7 @@ Image GetGTK0(GtkWidget *widget, int state, int shadow, const char *detail, int
if(GTK_IS_RANGE(widget)) {
GtkRange *r = GTK_RANGE(widget);
#ifndef GTK_NEWSCROLLBAR
r->has_stepper_a = r->has_stepper_b = r->has_stepper_c = r->has_stepper_d = 1;
// r->has_stepper_a = r->has_stepper_b = r->has_stepper_c = r->has_stepper_d = 1;
#endif
GdkRectangle cr;
cr.x = rect.left;
@ -661,4 +659,4 @@ void GtkChScrollBar(Value *lbutton, Value *lbutton2,
}
#endif
#endif
#endif

482
uppsrc/CtrlLib/ChGtk3.cpp Normal file
View file

@ -0,0 +1,482 @@
#include "CtrlLib.h"
#ifdef GUI_GTK
/*
TODO: overpaint
*/
namespace Upp {
int GtkSettingsInt(const char *name)
{
gint h = Null;
g_object_get(gtk_settings_get_default(), name, &h, NULL);
return h;
}
int GtkSettingsBool(const char *name)
{
gboolean h = false;
g_object_get(gtk_settings_get_default(), name, &h, NULL);
return h;
}
String GtkSettingsString(const char *name)
{
const char *h = "";
g_object_get(gtk_settings_get_default(), name, &h, NULL);
return h;
}
void SetupFont()
{
int fontface = Font::ARIAL;
int fontheight = 13;
bool bold = false;
bool italic = false;
String font_name = GtkSettingsString("gtk-font-name");
int xdpi = Nvl(GtkSettingsInt("gtk-xft-dpi"), 72 * 1024);
const char *q = strrchr(font_name, ' ');
if(q) {
int h = atoi(q);
if(h)
fontheight = h;
String face(font_name, q);
fontface = Font::FindFaceNameIndex(face);
if(fontface == 0) {
for(;;) {
const char *q = strrchr(face, ' ');
if(!q) break;
const char *s = q + 1;
if(stricmp(s, "Bold") == 0 || stricmp(s, "Heavy") == 0)
bold = true;
else
if(stricmp(s, "Italic") == 0 || stricmp(s, "Oblique") == 0)
italic = true;
else
if(stricmp(s, "Regular") == 0 || stricmp(s, "Light") || stricmp(s, "Medium"))
;
else
continue;
face = String(~face, q);
}
fontface = Font::FindFaceNameIndex(face);
if(fontface == 0) {
if(ToUpper(face[0]) == 'M')
fontface = Font::COURIER;
else
if(ToUpper(face[0]) == 'S' && ToUpper(face[1]) == 'e')
fontface = Font::ROMAN;
else
fontface = Font::ARIAL;
}
}
}
Font gui_font = Font(fontface, fround(Ctrl::SCL(fontheight) * xdpi + 512*72.0) / (1024*72)).Bold(bold).Italic(italic);
Font::SetDefaultFont(gui_font);
}
static Image sCurrentImage;
Image CairoImage(int cx, int cy, Event<cairo_t *> draw)
{
Image m[2];
for(int i = 0; i < 2; i++) {
ImageDraw iw(DPI(cx), DPI(cy));
iw.DrawRect(0, 0, DPI(cx), DPI(cy), i ? Black() : White());
cairo_t *cr = iw;
#if GTK_CHECK_VERSION(3, 20, 0)
cairo_surface_set_device_scale(cairo_get_target(cr), DPI(1), DPI(1));
#endif
draw(cr);
m[i] = iw;
}
sCurrentImage = RecreateAlpha(m[0], m[1]);
return sCurrentImage;
}
Image CairoImage(GtkStyleContext *ctx, int cx = 40, int cy = 32)
{
return CairoImage(cx, cy, [&](cairo_t *cr) {
gtk_render_background(ctx, cr, 0, 0, cx, cy);
gtk_render_frame(ctx, cr, 0, 0, cx, cy);
});
}
#if GTK_CHECK_VERSION(3, 20, 0)
static GtkStyleContext *sCtx = NULL;
static GtkStateFlags sFlags;
void Gtk_Free()
{
if(sCtx)
g_object_unref(sCtx);
sCtx = NULL;
}
void Gtk_State(int state, dword flags = 0)
{
sFlags = static_cast<GtkStateFlags>(decode(state, CTRL_HOT, GTK_STATE_FLAG_PRELIGHT,
CTRL_PRESSED, GTK_STATE_FLAG_ACTIVE,
CTRL_DISABLED, GTK_STATE_FLAG_INSENSITIVE,
GTK_STATE_FLAG_NORMAL) | flags) ;
gtk_style_context_set_state(sCtx, sFlags);
}
static Size sCurrentSize;
void Gtk_New(const char *name, int state = 0, dword flags = 0)
{
Gtk_Free();
sCtx = NULL;
for(const String& element : Split(name, ' ')) {
GtkWidgetPath *path = sCtx ? gtk_widget_path_copy(gtk_style_context_get_path(sCtx))
: gtk_widget_path_new();
Vector<String> s = Split(element, '.');
if(s.GetCount()) {
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, s[0]);
}
for(int i = 1; i < s.GetCount(); i++)
gtk_widget_path_iter_add_class(path, -1, s[i]);
GtkStyleContext *context2 = gtk_style_context_new();
gtk_style_context_set_path(context2, path);
gtk_style_context_set_parent(context2, sCtx);
gtk_widget_path_unref(path);
Gtk_Free();
sCtx = context2;
}
ASSERT(sCtx);
gtk_style_context_set_scale(sCtx, DPI(1));
Gtk_State(state, flags);
GtkBorder margin, border, padding;
int min_width, min_height;
GtkStateFlags f = gtk_style_context_get_state(sCtx);
gtk_style_context_get_margin (sCtx, f, &margin);
gtk_style_context_get_border (sCtx, f, &border);
gtk_style_context_get_padding (sCtx, f, &padding);
gtk_style_context_get(sCtx, f, "min-width", &min_width, "min-height", &min_height, NULL);
min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
sCurrentSize.cx = min_width;
sCurrentSize.cy = min_height;
}
/*
bool GtkStyleBool(const char *name)
{
return false;
gboolean b = false;
gtk_style_context_get(sCtx, gtk_style_context_get_state(sCtx), name, &b, NULL);
return b;
}
int GtkStyleInt(const char *name)
{
gint n = 0;
gtk_style_context_get(sCtx, gtk_style_context_get_state(sCtx), name, &n, NULL);
return n;
}
*/
Size GtkSize()
{
return sCurrentSize;
}
void GtkSize(Size& sz)
{
sz.cx = max(sz.cx, sCurrentSize.cx);
sz.cy = max(sz.cy, sCurrentSize.cy);
}
Color GetInkColor()
{
GdkRGBA color;
gtk_style_context_get_color(sCtx, sFlags, &color);
RGBA rgba;
rgba.r = int(255 * color.red);
rgba.g = int(255 * color.green);
rgba.b = int(255 * color.blue);
rgba.a = int(255 * color.alpha);
RGBA t = SColorPaper();
AlphaBlend(&t, &rgba, 1);
return t;
}
void SOImages(int imli, dword flags)
{
for(int st = 0; st < 4; st++) {
Gtk_State(st, flags);
CtrlsImg::Set(imli++, CairoImage(16, 16, [&](cairo_t *cr) {
gtk_render_check(sCtx, cr, 0, 0, 16, 16);
}));
}
}
Image CairoImage(int cx = 40, int cy = 32)
{
return CairoImage(sCtx, cx, cy);
}
Color GetBackgroundColor()
{
Image m = CairoImage(30, 30);
Image b = CreateImage(m.GetSize(), SColorPaper());
Over(b, m);
return AvgColor(b);
}
Image Gtk_Icon(const char *icon_name, int size)
{
GdkPixbuf *pixbuf = gtk_icon_theme_load_icon_for_scale(gtk_icon_theme_get_default(), icon_name,
size, 2, (GtkIconLookupFlags)0, NULL);
if(pixbuf) {
int cx = gdk_pixbuf_get_width(pixbuf);
int cy = gdk_pixbuf_get_height(pixbuf);
Image m = CairoImage(cx, cy, [&](cairo_t *cr) {
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
});
Size sz = m.GetSize();
g_object_unref(pixbuf);
return sz.cy > size && sz.cy ? Rescale(m, sz.cx * size / sz.cy, size) : m;
}
return Null;
}
void ChHostSkin()
{
SetupFont();
Gtk_New("label.view");
SColorPaper_Write(GetBackgroundColor());
SColorText_Write(GetInkColor());
Gtk_New("window.background");
SColorFace_Write(GetBackgroundColor());
Gtk_New("entry");
Gtk_State(CTRL_DISABLED);
SColorDisabled_Write(GetInkColor());
Gtk_New("entry selection");
SColorHighlight_Write(GetBackgroundColor());
SColorHighlightText_Write(GetInkColor());
Gtk_New("label.view");
SColorLabel_Write(GetInkColor());
Gtk_New("tooltip.background");
SColorInfo_Write(GetBackgroundColor());
SColorInfoText_Write(GetInkColor());
ColoredOverride(CtrlsImg::Iml(), CtrlsImg::Iml());
#if 0 // TODO (?)
{ SColorLight_Write, 2*5 + 0 },
{ SColorShadow_Write, 3*5 + 0 },
#endif
Gtk_New("radiobutton radio");
SOImages(CtrlsImg::I_S0, GTK_STATE_FLAG_NORMAL);
SOImages(CtrlsImg::I_S1, GTK_STATE_FLAG_CHECKED);
Gtk_New("checkbutton check");
SOImages(CtrlsImg::I_O0, GTK_STATE_FLAG_NORMAL);
SOImages(CtrlsImg::I_O1, GTK_STATE_FLAG_CHECKED);
SOImages(CtrlsImg::I_O2, GTK_STATE_FLAG_INCONSISTENT);
CtrlImg::Set(CtrlImg::I_MenuCheck0, CtrlsImg::O0());
CtrlImg::Set(CtrlImg::I_MenuCheck1, CtrlsImg::O1());
CtrlImg::Set(CtrlImg::I_MenuRadio0, CtrlsImg::S0());
CtrlImg::Set(CtrlImg::I_MenuRadio1, CtrlsImg::S1());
for(int i = 0; i < 6; i++)
CtrlsImg::Set(CtrlsImg::I_DA + i, CtrlsImg::Get(CtrlsImg::I_kDA + i));
{
Gtk_New("button");
Color ink;
Color text[4];
Image button[4];
for(int pass = 0; pass < 2; pass++) {
Button::Style& s = pass ? Button::StyleOk().Write() : Button::StyleNormal().Write();
int roundness = DPI(3);
for(int i = 0; i < 4; i++) {
Gtk_State(i);
s.look[i] = Hot3(CairoImage());
s.monocolor[i] = s.textcolor[i] = GetInkColor();
if(pass == 0) {
button[i] = WithHotSpots(CairoImage(100, 100), DPI(4), DPI(4), 0, 0);
text[i] = GetInkColor();
}
}
s.ok = Gtk_Icon("gtk-ok", DPI(16));
s.cancel = Gtk_Icon("gtk-cancel", DPI(16));
s.exit = Gtk_Icon("gtk-quit", DPI(16));
}
ChSynthetic(button, text);
{
auto& s = ToolButton::StyleDefault().Write();
s.look[CTRL_NORMAL] = Image();
s.look[CTRL_HOT] = button[CTRL_HOT];
s.look[CTRL_PRESSED] = button[CTRL_PRESSED];
s.look[CTRL_DISABLED] = Image();
s.look[CTRL_CHECKED] = button[CTRL_PRESSED];
s.look[CTRL_HOTCHECKED] = button[CTRL_HOT];
}
}
auto DialogIcon = [](int i, const char *s) { CtrlImg::Set(i, Gtk_Icon(s, DPI(48))); };
DialogIcon(CtrlImg::I_information, "gtk-dialog-info");
DialogIcon(CtrlImg::I_question, "gtk-dialog-question");
DialogIcon(CtrlImg::I_exclamation, "gtk-dialog-warning");
DialogIcon(CtrlImg::I_error, "gtk-dialog-error");
YesButtonImage_Write(Gtk_Icon("gtk-yes", DPI(16)));
NoButtonImage_Write(Gtk_Icon("gtk-no", DPI(16)));
AbortButtonImage_Write(Gtk_Icon("gtk-stop", DPI(16)));
RetryButtonImage_Write(Gtk_Icon("gtk-refresh", DPI(16)));
{
ScrollBar::Style& s = ScrollBar::StyleDefault().Write();
s.through = true;
static GtkWidget *proto = (GtkWidget *)gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL); // to get style params
gboolean stepper;
gint minslider;
gtk_widget_style_get(proto, "has-backward-stepper", &stepper, "min-slider-length", &minslider, NULL);
if(!stepper)
s.arrowsize = 0;
Gtk_New("scrollbar.horizontal.bottom");
Size sz = GtkSize();
Gtk_New("scrollbar.horizontal.bottom contents");
GtkSize(sz);
Gtk_New("scrollbar.horizontal.bottom contents trough");
GtkSize(sz);
Gtk_New("scrollbar.horizontal.bottom contents trough slider");
GtkSize(sz);
s.barsize = s.thumbwidth = DPI(sz.cy);
s.thumbmin = max(minslider, s.barsize);
sz.cx = 2 * sz.cy;
for(int status = CTRL_NORMAL; status <= CTRL_DISABLED; status++) {
Gtk_New("scrollbar.horizontal.bottom", status);
Image m = CairoImage(sz.cx, sz.cy);
Gtk_New("scrollbar.horizontal.bottom contents", status);
Over(m, CairoImage(sz.cx, sz.cy));
Gtk_New("scrollbar.horizontal.bottom contents trough", status);
Over(m, CairoImage(sz.cx, sz.cy));
s.hupper[status] = s.hlower[status] = ChHot(m);
s.vupper[status] = s.vlower[status] = ChHot(RotateAntiClockwise(m)); // we have problems getting this right for vertical
Gtk_New("scrollbar.horizontal.bottom contents trough slider", status);
s.hthumb[status] = ChHot(CairoImage(sz.cx, sz.cy));
Gtk_New("scrollbar.vertical.right contents trough slider", status);
GtkSize(sz);
s.vthumb[status] = ChHot(CairoImage(sz.cy, sz.cx));
}
}
{
MenuBar::Style& s = MenuBar::StyleDefault().Write();
s.pullshift.y = 0;
Gtk_New("menu");
Image m = CairoImage(32, 32);
s.pullshift.y = 0;
int mg = DPI(2);
s.popupframe = WithHotSpot(m, mg, mg);
Size sz = m.GetSize();
s.popupbody = Crop(m, mg, mg, sz.cx - 2 * mg, sz.cy - 2 * mg);
s.leftgap = DPI(16) + Zx(6);
SColorMenu_Write(GetBackgroundColor());
SColorMenuText_Write(s.menutext);
Gtk_New("menu menuitem");
s.menutext = GetInkColor();
Gtk_State(CTRL_HOT);
s.itemtext = GetInkColor();
Color c = AvgColor(m);
if(Diff(c, s.menutext) < 100) // menutext color too close to background color, fix it
s.menutext = IsDark(c) ? White() : Black();
s.item = Hot3(CairoImage(32, 16));
Gtk_New("menubar");
s.look = Hot3(CairoImage(32, 16));
Color dk = SColorText();
Color wh = SColorPaper();
if(IsDark(wh))
Swap(dk, wh);
s.topitemtext[0] = IsDark(AvgColor(sCurrentImage)) ? wh : dk;
s.topitem[1] = s.topitem[0] = Null;
s.topitemtext[1] = s.topitemtext[0];
Gtk_New("menubar menuitem", CTRL_HOT);
s.topitem[0] = Null;
s.topitem[2] = Hot3(CairoImage(32, 16));
s.topitemtext[2] = GetInkColor();
}
Gtk_Free();
}
Image GtkThemeIcon(const char *name, int rsz)
{
return Gtk_Icon(name, rsz);
}
#else
Image Gtk_Icon(const char *icon_name, int size)
{
GdkPixbuf *pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), icon_name,
size, (GtkIconLookupFlags)0, NULL);
if(pixbuf) {
int cx = gdk_pixbuf_get_width(pixbuf);
int cy = gdk_pixbuf_get_height(pixbuf);
Image m = CairoImage(cx, cy, [&](cairo_t *cr) {
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
});
Size sz = m.GetSize();
g_object_unref(pixbuf);
return sz.cy > size && sz.cy ? Rescale(m, sz.cx * size / sz.cy, size) : m;
}
return Null;
}
Image GtkThemeIcon(const char *name, int rsz)
{
return Gtk_Icon(name, rsz);
}
void ChHostSkin()
{
SetupFont();
}
#endif
};
#endif

View file

@ -25,26 +25,6 @@ s_colors[] = {
{ "Yellow", &Yellow },
{ "WhiteGray", &WhiteGray },
{ "White", &White },
//deprecated: (TODO)
{ "SBlack", &Black },
{ "SRed", &Red },
{ "SGreen", &Green },
{ "SBrown", &Brown },
{ "SBlue", &Blue },
{ "SMagenta", &Magenta },
{ "SCyan", &Cyan },
{ "SGray", &Gray },
{ "SLtGray", &LtGray },
{ "SLtRed", &LtRed },
{ "SLtGreen", &LtGreen },
{ "SLtYellow", &LtYellow },
{ "SLtBlue", &LtBlue },
{ "SLtMagenta", &LtMagenta },
{ "SLtCyan", &LtCyan },
{ "SYellow", &Yellow },
{ "SWhiteGray", &WhiteGray },
{ "SWhite", &White },
};
Color ColorPopUp::hint[18];
@ -102,16 +82,14 @@ ColorPopUp::~ColorPopUp() {}
int ColorPopUp::GetColorCount() const
{
return 18 + scolors * 18 + 2 * 18 + hints * 18 + 216;
return 18 + 2 * 18 + hints * 18 + 216;
}
Color ColorPopUp::GetColor(int i) const
{
if(!scolors)
i += 18;
if(i < 36)
if(i < 18)
return *s_colors[i].color;
i -= 36;
i -= 18;
if(i < 18)
return GrayColor(255 * (i + 1) / 20);
if(hints) {
@ -151,7 +129,7 @@ void ColorPopUp::Paint(Draw& w)
Size sz = GetSize();
int cy = GetCy();
w.DrawRect(sz, SColorMenu);
w.DrawRect(sz, SColorFace());
int y = DPI(1);
@ -207,8 +185,6 @@ void ColorPopUp::Paint(Draw& w)
}
DrawFilledFrame(w, x + DPI(1), y, DPI(14), DPI(14), SColorText, GetColor(i));
if(i < 18 && scolors)
DrawFrame(w, x + DPI(2), y + DPI(1), DPI(12), DPI(12), Blend(SColorLight, SColorHighlight));
if(i == colori) {
if(GetMouseLeft())
@ -397,7 +373,6 @@ ColorPopUp::ColorPopUp()
norampwheel = false;
notnull = false;
withvoid = false;
scolors = false;
animating = false;
hints = false;
open = false;

View file

@ -564,49 +564,49 @@ IMAGE_DATA(204,38,207,3,248,145,157,129,252,170,242,23,98,212,3,155,0,0,0,0,0,0,
IMAGE_END_DATA(1088, 24)
IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,89,127,76,148,101,28,63,214,218,250,163,77,182,230,90,70,118,215,106,108,55,87,76,87,203,149,113,148,72)
IMAGE_DATA(145,169,129,231,36,148,80,193,77,16,2,65,249,33,114,199,240,204,132,53,45,64,64,129,27,72,208,9,74,136,64,191)
IMAGE_DATA(140,12,52,202,22,135,168,152,53,12,21,144,129,153,6,136,202,251,233,158,247,120,239,222,247,238,121,239,184,67,59,215)
IMAGE_DATA(222,231,221,119,207,189,239,243,124,190,159,207,231,251,60,239,115,55,144,121,203,188,101,208,200,238,101,195,100,168,221,197)
IMAGE_DATA(27,12,6,46,135,59,121,64,90,75,75,11,180,90,45,84,42,149,171,121,88,188,9,1,249,63,114,104,207,104,93,205)
IMAGE_DATA(99,193,115,151,139,121,236,240,46,230,17,197,115,151,106,80,101,169,143,204,90,103,167,248,153,87,103,66,109,80,67,173)
IMAGE_DATA(86,59,90,31,59,60,31,167,84,42,167,236,223,69,156,0,79,188,185,136,179,224,109,234,226,242,254,115,19,231,249,54)
IMAGE_DATA(189,195,64,105,50,76,10,167,116,195,56,135,229,66,44,7,127,30,127,14,185,215,64,216,211,154,22,122,253,81,54,232)
IMAGE_DATA(115,196,112,102,110,149,42,159,197,146,151,135,124,182,215,233,8,79,94,92,3,139,35,120,161,6,103,250,205,220,4,207)
IMAGE_DATA(121,16,106,112,86,63,43,55,151,203,94,131,216,250,9,185,249,117,20,175,131,24,183,213,35,93,131,227,154,139,133,184)
IMAGE_DATA(6,51,183,92,190,11,194,250,104,45,58,196,53,88,235,68,207,111,29,167,207,49,115,155,15,90,3,37,191,117,156,62)
IMAGE_DATA(71,99,167,85,136,183,29,167,205,113,191,121,147,195,192,221,230,231,231,231,79,76,145,222,93,44,23,226,57,252,53,86)
IMAGE_DATA(227,254,150,99,139,182,65,232,120,45,114,115,15,33,53,181,154,186,1,197,113,164,153,23,127,231,206,90,52,55,127,75)
IMAGE_DATA(221,32,142,241,90,36,36,84,178,56,130,175,174,110,182,104,112,174,95,169,94,182,172,152,197,19,12,193,242,53,56,175)
IMAGE_DATA(159,153,155,228,224,124,216,106,16,95,63,33,183,76,38,247,167,105,112,230,219,204,109,127,24,240,53,136,213,252,126,31)
IMAGE_DATA(6,116,13,211,63,12,34,35,245,236,24,233,105,135,1,55,78,159,227,217,195,192,217,47,3,117,88,88,24,104,33,115)
IMAGE_DATA(252,51,136,197,45,85,7,162,173,171,22,195,232,16,4,121,70,198,68,242,168,249,184,33,24,237,240,220,51,46,15,63)
IMAGE_DATA(7,201,201,231,44,53,228,112,115,216,32,159,201,51,190,150,73,29,22,110,243,152,145,13,91,15,28,167,117,78,135,69)
IMAGE_DATA(131,144,219,72,237,105,120,78,3,9,62,183,48,204,94,222,92,162,226,233,183,142,77,5,47,244,98,116,1,79,211,237)
IMAGE_DATA(26,94,156,91,136,23,211,71,214,206,145,54,110,47,209,52,14,217,244,52,109,220,30,18,211,96,230,119,200,77,221,191)
IMAGE_DATA(214,176,221,15,244,253,123,15,222,31,247,223,95,185,204,139,127,11,143,246,94,38,57,15,140,24,185,141,24,128,253,238)
IMAGE_DATA(246,72,239,73,238,201,130,72,254,37,255,146,127,201,191,228,95,242,47,249,151,252,75,254,37,255,146,127,201,191,228,95)
IMAGE_DATA(242,255,255,247,255,144,233,114,208,96,247,196,17,224,98,72,136,83,0,249,75,205,16,175,39,128,83,147,247,39,216,222)
IMAGE_DATA(22,48,153,149,237,185,224,63,111,241,146,61,102,153,173,8,45,130,34,116,159,41,74,161,88,94,14,197,138,42,40,194)
IMAGE_DATA(106,161,88,213,0,69,228,55,80,68,183,225,233,216,95,241,212,166,223,224,147,122,5,62,25,215,224,147,57,2,31,205)
IMAGE_DATA(109,83,76,152,2,150,144,61,34,123,212,81,113,238,119,179,175,165,112,12,34,115,64,9,71,99,98,121,30,172,230,225)
IMAGE_DATA(197,112,167,77,165,216,83,89,136,169,44,210,127,186,128,199,167,243,127,215,7,173,49,169,201,96,99,203,38,76,36,198)
IMAGE_DATA(227,238,198,24,164,124,54,136,228,3,3,136,215,15,32,182,164,15,209,69,151,17,145,223,139,160,249,222,161,221,149,43)
IMAGE_DATA(113,225,11,29,58,74,22,97,241,75,51,34,88,236,215,205,96,190,108,4,211,120,4,204,145,58,4,110,239,193,39,77)
IMAGE_DATA(67,72,173,236,67,82,121,31,116,181,87,17,181,163,0,253,199,82,112,189,179,1,184,121,5,127,117,214,224,168,38,96)
IMAGE_DATA(96,34,41,1,76,83,3,24,93,22,152,172,12,48,135,107,48,127,235,121,236,170,31,68,124,217,101,196,236,191,132,178)
IMAGE_DATA(154,74,92,237,212,98,252,82,61,250,91,114,48,122,250,16,238,94,108,197,169,226,181,99,68,47,225,100,50,211,192,164)
IMAGE_DATA(109,6,99,168,134,50,185,27,217,181,3,136,46,236,133,174,172,6,195,93,219,48,49,218,138,209,63,54,98,248,167,56)
IMAGE_DATA(156,171,88,135,246,253,171,176,190,108,9,110,71,173,99,57,137,127,38,49,14,204,129,114,204,222,112,22,91,171,250,145)
IMAGE_DATA(85,252,57,174,157,78,195,196,216,73,140,252,254,62,198,122,195,113,227,108,58,46,148,6,163,174,181,24,239,20,4,226)
IMAGE_DATA(86,120,56,203,201,124,16,11,102,67,52,24,125,41,102,69,26,145,83,168,71,255,207,41,147,216,8,140,253,249,30,254)
IMAGE_DATA(238,218,138,115,123,23,97,247,225,36,84,252,82,133,133,57,11,48,250,110,40,203,201,172,95,11,102,205,106,48,251,138)
IMAGE_DATA(240,118,84,30,186,154,182,152,52,31,199,88,207,58,220,234,93,141,235,38,29,231,247,6,97,71,125,10,146,234,211,176)
IMAGE_DATA(255,71,61,94,213,190,136,145,160,96,150,147,137,48,233,8,91,129,110,221,122,156,105,76,135,177,105,55,46,183,171,49)
IMAGE_DATA(210,19,142,225,142,84,180,231,46,198,193,214,34,36,214,165,32,230,96,2,10,76,250,231,109,121,30,55,23,4,176,156)
IMAGE_DATA(76,97,1,152,252,79,97,248,232,13,224,198,69,116,23,47,199,177,244,89,104,43,124,11,141,217,129,152,251,90,53,74)
IMAGE_DATA(219,203,81,116,162,4,249,63,20,98,79,75,30,230,196,249,66,187,240,67,100,250,103,99,219,203,26,100,204,203,64,118)
IMAGE_DATA(212,28,140,159,204,195,120,251,30,180,235,2,80,177,230,89,188,48,191,18,51,124,191,195,115,75,51,160,8,78,199,236)
IMAGE_DATA(69,41,120,242,245,205,120,194,63,201,238,197,13,121,197,123,108,251,106,223,59,95,233,130,238,124,28,51,247,251,199,103)
IMAGE_DATA(60,252,140,39,222,139,169,182,127,1,101,189,88,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_DATA(120,156,237,89,123,76,83,87,28,190,102,89,178,63,150,72,178,152,101,46,49,221,178,133,164,49,155,209,108,25,217,28)
IMAGE_DATA(101,19,216,156,83,167,235,50,134,48,148,71,34,10,131,161,188,68,169,193,58,39,102,209,77,16,24,143,6,100,178,10)
IMAGE_DATA(202,80,129,109,153,99,14,117,168,75,0,121,63,228,253,28,108,62,38,232,148,251,173,231,150,219,222,219,158,219,210,162)
IMAGE_DATA(43,89,238,185,249,229,244,222,115,190,223,247,125,191,115,238,105,3,140,27,227,198,32,153,121,144,13,211,161,118,22,175)
IMAGE_DATA(215,235,249,28,206,228,1,105,85,85,85,208,104,52,80,169,84,142,230,225,240,6,4,20,127,43,160,105,212,56,154,199)
IMAGE_DATA(132,231,47,7,243,88,225,29,204,35,137,231,47,213,168,202,84,31,198,92,103,187,248,5,35,11,160,214,171,161,86,171)
IMAGE_DATA(109,173,143,21,94,136,83,42,149,51,246,239,32,78,132,39,222,28,196,153,240,22,117,113,120,255,57,137,115,125,155,221)
IMAGE_DATA(97,160,52,24,38,133,83,58,97,156,199,242,33,149,67,56,79,56,135,220,39,67,220,211,154,6,58,221,25,46,232,115)
IMAGE_DATA(164,112,70,110,149,42,141,195,146,151,135,124,182,214,105,11,79,94,92,61,135,35,120,177,6,123,250,141,220,4,207,123)
IMAGE_DATA(16,107,176,87,63,51,55,159,203,90,131,212,250,137,185,133,117,148,174,131,20,183,217,35,93,131,237,154,75,133,180,6)
IMAGE_DATA(35,183,66,177,31,226,250,104,76,58,164,53,152,235,68,207,111,30,167,207,49,114,27,15,90,61,37,191,121,156,62,39)
IMAGE_DATA(217,74,171,24,111,57,78,155,227,124,115,35,135,129,179,109,201,146,37,158,196,20,233,157,197,242,33,157,195,51,217,108)
IMAGE_DATA(220,211,116,108,209,54,8,29,175,193,129,3,39,16,31,95,68,221,128,210,56,210,140,139,191,111,95,9,42,43,127,162)
IMAGE_DATA(110,16,219,120,13,162,162,10,57,28,193,23,21,85,154,52,216,215,175,84,175,93,155,197,225,9,134,96,133,26,236,215)
IMAGE_DATA(207,200,77,114,240,62,44,53,72,175,159,152,155,97,20,158,52,13,246,124,27,185,173,15,3,161,6,169,154,63,236,195)
IMAGE_DATA(128,174,97,246,135,65,80,144,142,27,35,61,237,48,224,199,233,115,92,123,24,216,251,101,160,246,243,243,3,45,24,219)
IMAGE_DATA(63,131,56,220,26,181,55,206,55,148,96,28,181,162,32,207,200,152,68,30,181,16,55,134,58,43,60,255,140,207,35,204)
IMAGE_DATA(65,114,10,57,115,245,169,252,28,46,200,103,242,76,168,101,90,135,137,219,56,86,199,133,165,7,158,211,60,167,214,164)
IMAGE_DATA(65,204,93,71,237,105,120,94,3,9,33,183,56,140,94,222,90,173,18,232,55,143,205,4,47,246,82,231,0,158,166,219)
IMAGE_DATA(49,188,52,183,24,47,165,143,172,157,45,109,252,94,162,105,28,179,232,105,218,248,61,36,165,193,200,111,147,155,186,127)
IMAGE_DATA(205,97,185,31,232,251,247,1,188,63,206,191,191,10,102,158,240,22,46,237,231,25,228,204,25,49,10,11,49,0,247,221)
IMAGE_DATA(237,146,222,149,220,211,5,145,253,203,254,101,255,178,127,217,191,236,95,246,47,251,151,253,203,254,101,255,178,127,217,191)
IMAGE_DATA(236,255,255,239,255,17,195,101,163,193,234,137,45,64,247,186,117,118,1,228,47,53,99,130,158,0,174,76,223,95,224,122)
IMAGE_DATA(75,192,116,86,174,231,67,248,156,153,199,60,97,154,125,227,198,4,174,54,180,161,161,177,29,141,77,29,104,106,238,68)
IMAGE_DATA(115,235,53,180,182,117,163,173,189,7,237,29,189,232,184,214,135,206,174,126,92,235,30,64,119,207,16,122,250,134,209,219)
IMAGE_DATA(63,130,190,129,81,244,15,254,129,129,161,49,92,186,92,11,230,49,230,113,91,197,121,216,205,186,150,226,49,72,204,1)
IMAGE_DATA(37,108,141,73,229,153,91,205,197,139,225,76,155,73,177,103,178,16,51,89,164,255,116,1,207,205,230,255,174,115,173,177)
IMAGE_DATA(241,219,192,69,236,167,152,138,142,196,253,173,225,136,251,102,20,219,142,14,35,82,55,140,45,57,131,8,205,236,71,96)
IMAGE_DATA(90,47,124,61,220,214,183,20,126,136,246,239,180,168,205,241,193,170,151,231,7,114,216,31,43,193,126,95,14,182,252,20)
IMAGE_DATA(216,83,165,240,222,211,133,47,43,198,16,95,56,136,152,252,65,104,75,70,16,178,55,29,67,103,227,112,189,254,52,112)
IMAGE_DATA(107,0,127,213,23,227,76,178,215,240,84,76,20,216,138,211,96,181,187,193,238,78,2,123,178,24,30,59,90,177,191,108)
IMAGE_DATA(20,145,121,253,8,207,238,67,94,113,33,70,234,53,184,219,87,134,161,170,84,76,92,61,129,251,221,213,184,146,181,105)
IMAGE_DATA(146,232,37,156,236,174,4,176,9,219,193,234,139,160,220,214,130,148,146,97,132,102,244,66,155,87,140,241,134,157,152,154)
IMAGE_DATA(168,198,68,231,86,140,95,138,64,115,65,48,106,178,55,32,44,111,53,254,9,9,230,56,137,127,54,58,2,236,209,124)
IMAGE_DATA(44,218,220,132,29,199,134,176,59,235,91,252,121,53,1,83,147,23,113,187,227,99,76,246,250,227,102,83,34,218,115,87)
IMAGE_DATA(162,180,58,11,239,166,123,227,142,191,63,199,201,126,178,5,236,230,80,176,186,92,44,12,170,67,106,134,14,67,151,227)
IMAGE_DATA(166,177,129,152,236,249,8,55,26,118,160,249,136,15,14,158,140,65,193,239,199,176,34,117,57,38,222,91,207,113,178,97)
IMAGE_DATA(155,192,110,12,0,251,117,38,222,9,57,140,134,138,88,131,230,115,152,236,10,198,157,222,0,92,55,232,104,61,226,139)
IMAGE_DATA(189,101,113,136,41,75,64,246,111,58,188,166,121,9,183,125,87,114,156,108,160,65,135,223,7,104,209,134,161,177,60,17)
IMAGE_DATA(117,21,7,209,95,163,198,237,46,127,140,215,198,163,230,192,42,28,175,206,68,116,105,28,194,143,71,33,221,160,127,89)
IMAGE_DATA(236,11,184,181,220,139,227,100,51,210,193,166,125,5,253,231,111,2,55,187,209,146,245,62,206,38,46,196,249,140,183,81)
IMAGE_DATA(158,226,141,165,175,23,33,183,38,31,153,23,114,144,246,107,6,14,85,29,198,226,8,119,104,86,124,134,93,158,41,216)
IMAGE_DATA(249,74,50,146,150,37,33,37,100,49,238,94,60,140,187,53,135,80,163,245,66,193,198,231,240,162,71,33,230,187,255,140)
IMAGE_DATA(231,215,36,225,153,149,137,88,228,19,135,167,223,216,142,167,60,99,172,94,220,117,175,186,77,238,9,112,191,247,131,214)
IMAGE_DATA(247,222,23,225,75,127,121,114,254,163,207,186,226,189,152,105,251,23,36,79,112,33,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(1440, 15)

View file

@ -2,7 +2,6 @@
#define CTRLLIB_H
#include <CtrlCore/CtrlCore.h>
#include <Painter/Painter.h>
#ifdef Status //X11 defines this, likely name clash...
#undef Status

View file

@ -116,6 +116,7 @@ file
ChGtk.h,
ChGtk0.cpp,
ChGtk.cpp,
ChGtk3.cpp,
ChCocoMM.h,
ChCocoMM.mm,
ChCoco.h,

View file

@ -165,7 +165,6 @@ private:
int colori;
bool notnull;
bool scolors;
bool norampwheel;
bool animating;
bool hints;
@ -196,7 +195,6 @@ public:
Color Get() const;
ColorPopUp& NotNull(bool b = true) { notnull = b; return *this; }
ColorPopUp& SColors(bool b = true) { scolors = b; return *this; }//Deprecated
ColorPopUp& NullText(const char *s) { nulltext = s; Refresh(); return *this; }
ColorPopUp& WithVoid(bool b = true) { withvoid = b; Refresh(); return *this; }
ColorPopUp& VoidText(const char *s) { voidtext = s; Refresh(); return *this; }
@ -239,7 +237,6 @@ public:
ColorPusher& NotNull(bool b = true) { colors.NotNull(b); return *this; }
ColorPusher& WithVoid(bool b = true) { colors.WithVoid(b); return *this; }
ColorPusher& VoidText(const char *s) { voidtext = s; colors.VoidText(s); Refresh(); return *this; }
ColorPusher& SColors(bool b = true) { colors.SColors(b); return *this; }
ColorPusher& WithText() { withtext = true; Refresh(); return *this; }
ColorPusher& WithHex() { withhex = true; Refresh(); return *this; }
ColorPusher& Track(bool b = true) { track = b; return *this; }

View file

@ -7,7 +7,7 @@ DropChoice::DropChoice() {
AddButton().Main() <<= THISBACK(Drop);
NoDisplay();
list.Normal();
list.WhenSelect = callback(this, &DropChoice::Select);
list.WhenSelect = [=] { Select(); };
dropfocus = true;
EnableDrop(false);
dropwidth = 0;

View file

@ -110,7 +110,7 @@ void ActiveEdgeFrame::FramePaint(Draw& w, const Rect& r)
{
int i = 0;
if(ctrl) {
i = !ctrl->IsEnabled() ? CTRL_DISABLED
i = !ctrl->IsEnabled() || ctrl->IsReadOnly() ? CTRL_DISABLED
: ctrl->HasFocus() ? CTRL_PRESSED
: mousein ? CTRL_HOT
: CTRL_NORMAL;

View file

@ -182,8 +182,8 @@ void MenuItemBase::PaintTopItem(Draw& w, int state) {
w.DrawRect(0, 0, sz.cx, sz.cy, bg);
Color txt = opaque ? style->topitemtext[0] : GetLabelTextColor(this);
Color hltxt = opaque2 ? style->topitemtext[state] : GetLabelTextColor(this);
if(!opaque && state != PUSH && style->opaquetest) { // Fix issues when text color is not compatible with transparent background (e.g. Ubuntu Ambience)]
Color c = state == 2 ? SColorHighlight() : bg;
if(!opaque && state != 2 && style->opaquetest) { // Fix issues when text color is not compatible with transparent background (e.g. Ubuntu Ambience)]
Color c = state == 1 && !IsNull(style->topitem[0]) ? SColorHighlight() : bg;
int g = Grayscale(c);
bool dark = IsDark(c);
if(abs(g - Grayscale(txt)) < 70)

View file

@ -282,7 +282,7 @@ int MultiButton::ChState(int i)
if(i == MAIN && frm && style->activeedge) {
int q = 0;
if(p)
q = !p->IsEnabled() || !IsEnabled() || IsReadOnly() || i >= 0 && !button[i].enabled ? CTRL_DISABLED
q = !p->IsEnabled() || !IsEnabled() || p->IsReadOnly() || i >= 0 && !button[i].enabled ? CTRL_DISABLED
: p->HasFocus() || push ? CTRL_PRESSED
: p->HasMouse() || hl >= 0 ? CTRL_HOT
: CTRL_NORMAL;

View file

@ -10,6 +10,7 @@ CH_STYLE(ProgressIndicator, Style, StyleDefault)
vlook = CtrlsImg::VPI();
vchunk = CtrlsImg::VPIC();
bound = false;
nomargins = false;
}
Size ProgressIndicator::GetMsz()
@ -74,6 +75,8 @@ void ProgressIndicator::Paint(Draw& w) {
if(sz.cy > sz.cx) {
ChPaint(w, sz, style->vlook);
Rect r = ChMargins(style->vlook);
if(style->nomargins)
r.left = r.right = r.top = r.bottom = 0;
w.Clip(r.left, r.top, sz.cx - r.left - r.right, sz.cy - r.top - r.bottom);
ChPaint(w, r.left, sz.cy - r.bottom - p - p0, sz.cx - r.left - r.right, p,
style->vchunk);
@ -81,6 +84,8 @@ void ProgressIndicator::Paint(Draw& w) {
else {
ChPaint(w, sz, style->hlook);
Rect r = ChMargins(style->hlook);
if(style->nomargins)
r.left = r.right = r.top = r.bottom = 0;
w.Clip(r.left, r.top, sz.cx - r.left - r.right, sz.cy - r.top - r.bottom);
ChPaint(w, r.left + p0, r.top, p, sz.cy - r.top - r.bottom, style->hchunk);
}

View file

@ -7,6 +7,7 @@ public:
struct Style : ChStyle<Style> {
bool classic;
bool bound;
bool nomargins;
Value vlook, vchunk, hlook, hchunk;
};

View file

@ -111,6 +111,8 @@ Rect LabelBox::GetVoidRect() const
return r;
}
Value LabelBox::LabelBoxLook;
void PaintLabelBox(Draw& w, Size sz, Color color, int d)
{
bool hline = sz.cy < 2 * Draw::GetStdFontCy();
@ -130,23 +132,31 @@ void PaintLabelBox(Draw& w, Size sz, Color color, int d)
w.DrawRect(d + 1, 0, 1, sz.cy, SColorLight);
}
else {
Color c = Nvl(color, LabelBoxColor);
w.DrawRect(0, d + 2, 1, sz.cy - d - 4, c);
w.DrawRect(sz.cx - 1, d + 2, 1, sz.cy - d - 4, c);
w.DrawRect(2, sz.cy - 1, sz.cx - 4, 1, c);
w.DrawRect(2, d, sz.cx - 4, 1, c);
w.DrawRect(1, d + 1, 2, 1, c);
w.DrawRect(1, d + 2, 1, 1, c);
w.DrawRect(sz.cx - 3, d + 1, 2, 1, c);
w.DrawRect(sz.cx - 2, d + 2, 1, 1, c);
w.DrawRect(1, sz.cy - 2, 2, 1, c);
w.DrawRect(1, sz.cy - 3, 1, 1, c);
w.DrawRect(sz.cx - 3, sz.cy - 2, 2, 1, c);
w.DrawRect(sz.cx - 2, sz.cy - 3, 1, 1, c);
Value look = LabelBox::GetLook();
if(IsNull(look) || !IsNull(color)) {
Color c = Nvl(color, LabelBoxColor);
w.DrawRect(0, d + 2, 1, sz.cy - d - 4, c);
w.DrawRect(sz.cx - 1, d + 2, 1, sz.cy - d - 4, c);
w.DrawRect(2, sz.cy - 1, sz.cx - 4, 1, c);
w.DrawRect(2, d, sz.cx - 4, 1, c);
w.DrawRect(1, d + 1, 2, 1, c);
w.DrawRect(1, d + 2, 1, 1, c);
w.DrawRect(sz.cx - 3, d + 1, 2, 1, c);
w.DrawRect(sz.cx - 2, d + 2, 1, 1, c);
w.DrawRect(1, sz.cy - 2, 2, 1, c);
w.DrawRect(1, sz.cy - 3, 1, 1, c);
w.DrawRect(sz.cx - 3, sz.cy - 2, 2, 1, c);
w.DrawRect(sz.cx - 2, sz.cy - 3, 1, 1, c);
}
else {
Rect r = sz;
r.top = d;
ChPaintEdge(w, r, look);
}
}
}
else {

View file

@ -41,10 +41,16 @@ public:
virtual void AssignAccessKeys(dword used);
virtual Rect GetVoidRect() const;
Color color;
static Value LabelBoxLook;
public:
LabelBox& SetColor(Color c) { color = c; return *this; }
static void SetLook(const Value& v) { LabelBoxLook = v; }
static Value GetLook() { return LabelBoxLook; }
LabelBox& SetColor(Color c) { color = c; return *this; }
LabelBox();
virtual ~LabelBox();

View file

@ -185,7 +185,7 @@ struct ColorProperty : public EditorProperty<ColorPusher> {
ColorProperty() {
Add(editor.HSizePosZ(100, 2).TopPos(2));
editor.WithText().SColors().NullText("Null").Track();
editor.WithText().NullText("Null").Track();
}
static ItemProperty *Create() { return new ColorProperty; }