c02be7127f
[GB.QT4] * BUG: Fix ComboBox look with Oxygen style. [GB.QT5] * BUG: Fix ComboBox look with Oxygen style.
528 lines
14 KiB
C++
528 lines
14 KiB
C++
/***************************************************************************
|
|
|
|
CStyle.cpp
|
|
|
|
(c) 2000-2017 Benoît Minisini <gambas@users.sourceforge.net>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#define __CStyle_CPP
|
|
|
|
#include <QApplication>
|
|
#include <QToolTip>
|
|
|
|
#include "gambas.h"
|
|
#include "main.h"
|
|
#include "gb.draw.h"
|
|
#include "cpaint_impl.h"
|
|
#include "CPicture.h"
|
|
#include "CWidget.h"
|
|
#include "CWindow.h"
|
|
#include "CFont.h"
|
|
#include "CScreen.h"
|
|
|
|
#ifndef NO_X_WINDOW
|
|
#include <QX11Info>
|
|
#include "x11.h"
|
|
#endif
|
|
|
|
bool CSTYLE_fix_breeze = false;
|
|
bool CSTYLE_fix_oxygen = false;
|
|
|
|
static char *_style_name = NULL;
|
|
|
|
static QWidget *_fake = 0;
|
|
|
|
static QWidget *get_fake_widget()
|
|
{
|
|
if (!_fake)
|
|
_fake = new QWidget;
|
|
return _fake;
|
|
}
|
|
|
|
static char *get_style_name()
|
|
{
|
|
if (!_style_name)
|
|
{
|
|
if (CSTYLE_fix_breeze)
|
|
{
|
|
_style_name = GB.NewZeroString("Breeze");
|
|
}
|
|
else if (CSTYLE_fix_oxygen)
|
|
{
|
|
_style_name = GB.NewZeroString("Oxygen");
|
|
}
|
|
else
|
|
{
|
|
const char *name = qApp->style()->metaObject()->className();
|
|
int len = strlen(name);
|
|
|
|
if (len >= 6 && strncasecmp(&name[len - 5], "style", 5) == 0)
|
|
len -= 5;
|
|
if (len >= 3 && strncmp(&name[len - 2], "::", 2) == 0)
|
|
len -= 2;
|
|
if (name[0] == 'Q' && isupper(name[1]))
|
|
{
|
|
len--;
|
|
name++;
|
|
}
|
|
|
|
_style_name = GB.NewString(name, len);
|
|
}
|
|
}
|
|
|
|
return _style_name;
|
|
}
|
|
|
|
static void init_option(QStyleOption &opt, int x, int y, int w, int h, int state, GB_COLOR color = COLOR_DEFAULT, QPalette::ColorRole role = QPalette::Window)
|
|
{
|
|
opt.rect = QRect(x, y, w ,h);
|
|
opt.state = QStyle::State_None;
|
|
|
|
if (!(state & GB_DRAW_STATE_DISABLED))
|
|
opt.state |= QStyle::State_Enabled;
|
|
if (state & GB_DRAW_STATE_FOCUS)
|
|
opt.state |= QStyle::State_HasFocus;
|
|
if (state & GB_DRAW_STATE_HOVER)
|
|
opt.state |= QStyle::State_MouseOver;
|
|
if (state & GB_DRAW_STATE_ACTIVE)
|
|
opt.state |= QStyle::State_On | QStyle::State_Sunken | QStyle::State_Active;
|
|
|
|
if (color != GB_COLOR_DEFAULT)
|
|
{
|
|
QPalette palette;
|
|
palette.setColor(role, TO_QCOLOR(color));
|
|
opt.palette = palette;
|
|
}
|
|
}
|
|
|
|
static void paint_focus(QPainter *p, int x, int y, int w, int h, int state)
|
|
{
|
|
//bool do_clip = FALSE;
|
|
QStyleOptionFocusRect opt;
|
|
|
|
if ((state & GB_DRAW_STATE_DISABLED) || !(state & GB_DRAW_STATE_FOCUS))
|
|
return;
|
|
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
/*if (::strcmp(qApp->style()->metaObject()->className(), "QtCurve::Style") == 0)
|
|
{
|
|
QPainterPath clip;
|
|
|
|
p->save();
|
|
|
|
clip.addRect(x, y, w, 1);
|
|
clip.addRect(x, y, 1, h);
|
|
clip.addRect(x, y + h - 1, w, 1);
|
|
clip.addRect(x + w - 1, y, 1, h);
|
|
p->setClipPath(clip);
|
|
do_clip = TRUE;
|
|
}*/
|
|
|
|
p->save();
|
|
p->setBrush(QBrush());
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p);
|
|
|
|
p->restore();
|
|
|
|
/*if (do_clip)
|
|
p->restore();*/
|
|
}
|
|
|
|
static void style_arrow(QPainter *p, int x, int y, int w, int h, int type, int state)
|
|
{
|
|
QStyleOption opt;
|
|
QStyle::PrimitiveElement pe;
|
|
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
switch (type)
|
|
{
|
|
case ALIGN_NORMAL: pe = GB.System.IsRightToLeft() ? QStyle::PE_IndicatorArrowLeft : QStyle::PE_IndicatorArrowRight; break;
|
|
case ALIGN_LEFT: pe = QStyle::PE_IndicatorArrowLeft; break;
|
|
case ALIGN_RIGHT: pe = QStyle::PE_IndicatorArrowRight; break;
|
|
case ALIGN_TOP: pe = QStyle::PE_IndicatorArrowUp; break;
|
|
case ALIGN_BOTTOM: pe = QStyle::PE_IndicatorArrowDown; break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
QApplication::style()->drawPrimitive(pe, &opt, p);
|
|
}
|
|
|
|
static void style_check(QPainter *p, int x, int y, int w, int h, int value, int state)
|
|
{
|
|
QStyleOptionButton opt;
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
if (value)
|
|
{
|
|
if (value == 1)
|
|
opt.state |= QStyle::State_NoChange;
|
|
else
|
|
opt.state |= QStyle::State_On;
|
|
}
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, p);
|
|
paint_focus(p, x, y, w, h, state);
|
|
}
|
|
|
|
static void style_option(QPainter *p, int x, int y, int w, int h, int value, int state)
|
|
{
|
|
QStyleOptionButton opt;
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
if (value)
|
|
opt.state |= QStyle::State_On;
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorRadioButton, &opt, p);
|
|
paint_focus(p, x, y, w, h, state);
|
|
}
|
|
|
|
static void style_separator(QPainter *p, int x, int y, int w, int h, int vertical, int state)
|
|
{
|
|
QStyleOption opt;
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
if (vertical)
|
|
opt.state |= QStyle::State_Horizontal;
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, p);
|
|
}
|
|
|
|
|
|
static void style_button(QPainter *p, int x, int y, int w, int h, int value, int state, int flat)
|
|
{
|
|
if (flat)
|
|
{
|
|
QStyleOptionToolButton opt;
|
|
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
//opt.state |= QStyle::State_Raised;
|
|
|
|
if (value)
|
|
opt.state |= QStyle::State_On;
|
|
|
|
//opt.state &= ~QStyle::State_HasFocus;
|
|
opt.state |= QStyle::State_AutoRaise;
|
|
if (opt.state & QStyle::State_MouseOver)
|
|
opt.state |= QStyle::State_Raised;
|
|
|
|
if (opt.state & (QStyle::State_Sunken | QStyle::State_On | QStyle::State_MouseOver))
|
|
{
|
|
QApplication::style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, p);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QStyleOptionButton opt;
|
|
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
opt.state |= QStyle::State_Raised;
|
|
|
|
if (value)
|
|
opt.state |= QStyle::State_On;
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, p);
|
|
}
|
|
|
|
paint_focus(p, x, y, w, h, state);
|
|
}
|
|
|
|
static void style_panel(QPainter *p, int x, int y, int w, int h, int border, int state)
|
|
{
|
|
QStyleOptionFrame opt;
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
CCONTAINER_draw_border_without_widget(p, border, opt);
|
|
}
|
|
|
|
static void style_handle(QPainter *p, int x, int y, int w, int h, int vertical, int state)
|
|
{
|
|
QStyleOption opt;
|
|
init_option(opt, x, y, w, h, state);
|
|
|
|
if (!vertical)
|
|
opt.state |= QStyle::State_Horizontal;
|
|
|
|
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p);
|
|
paint_focus(p, x, y, w, h, state);
|
|
}
|
|
|
|
|
|
static void style_box(QPainter *p, int x, int y, int w, int h, int state, GB_COLOR color)
|
|
{
|
|
QStyleOptionFrame opt;
|
|
|
|
//if (GB.Is(d->device, CLASS_DrawingArea))
|
|
// opt.initFrom(QWIDGET(d->device));
|
|
|
|
init_option(opt, x, y, w, h, state, color, QPalette::Base);
|
|
|
|
opt.lineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt);
|
|
opt.midLineWidth = 0;
|
|
opt.state |= QStyle::State_Sunken;
|
|
p->save();
|
|
p->setBrush(Qt::NoBrush);
|
|
//opt.features = QStyleOptionFrameV2::None;
|
|
|
|
if (color == GB_COLOR_DEFAULT)
|
|
QApplication::style()->drawPrimitive(QStyle::PE_FrameLineEdit, &opt, p);
|
|
else
|
|
{
|
|
if (::strcmp(qApp->style()->metaObject()->className(), "QGtkStyle") == 0)
|
|
{
|
|
QWidget *w = get_fake_widget();
|
|
w->setAttribute(Qt::WA_SetPalette, true);
|
|
QApplication::style()->drawPrimitive(QStyle::PE_PanelLineEdit, &opt, p, w);
|
|
w->setAttribute(Qt::WA_SetPalette, false);
|
|
}
|
|
else
|
|
QApplication::style()->drawPrimitive(QStyle::PE_PanelLineEdit, &opt, p);
|
|
}
|
|
|
|
p->restore();
|
|
//paint_focus(d, x, y, w, h, state);
|
|
//if (state & GB_DRAW_STATE_FOCUS)
|
|
// QApplication::style()->drawControl(QStyle::CE_FocusFrame, &opt, DP(d), GB.Is(d->device, CLASS_DrawingArea) ? QWIDGET(d->device) : NULL);
|
|
}
|
|
|
|
BEGIN_PROPERTY(Style_ScrollbarSize)
|
|
|
|
GB.ReturnInteger(qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(Style_ScrollbarSpacing)
|
|
|
|
if (::strcmp(get_style_name(), "Breeze") == 0)
|
|
GB.ReturnInteger(0);
|
|
else
|
|
GB.ReturnInteger(qMax(0, qApp->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing)));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(Style_FrameWidth)
|
|
|
|
if (::strcmp(get_style_name(), "Breeze") == 0)
|
|
GB.ReturnInteger(2);
|
|
else
|
|
GB.ReturnInteger(qApp->style()->pixelMetric(QStyle::QStyle::PM_ComboBoxFrameWidth));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(Style_BoxFrameWidth)
|
|
|
|
if (::strcmp(get_style_name(), "Breeze") == 0)
|
|
GB.ReturnInteger(2);
|
|
else
|
|
{
|
|
int w = qApp->style()->pixelMetric(QStyle::QStyle::PM_ComboBoxFrameWidth);
|
|
|
|
if (::strcmp(get_style_name(), "Oxygen") == 0)
|
|
w++;
|
|
|
|
GB.ReturnInteger(w);
|
|
}
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(Style_Name)
|
|
|
|
GB.ReturnString(get_style_name());
|
|
|
|
END_PROPERTY
|
|
|
|
#define GET_COORD() \
|
|
int x, y, w, h; \
|
|
\
|
|
QPainter *p = PAINT_get_current(); \
|
|
if (!p) \
|
|
return; \
|
|
\
|
|
x = VARG(x); \
|
|
y = VARG(y); \
|
|
w = VARG(w); \
|
|
h = VARG(h); \
|
|
\
|
|
if (w < 1 || h < 1) \
|
|
return;
|
|
|
|
BEGIN_METHOD(Style_PaintArrow, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_INTEGER type; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_arrow(p, x, y, w, h, VARG(type), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintCheck, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_INTEGER value; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_check(p, x, y, w, h, VARG(value), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintOption, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_BOOLEAN value; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_option(p, x, y, w, h, VARG(value), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintSeparator, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_BOOLEAN vertical; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_separator(p, x, y, w, h, VARGOPT(vertical, FALSE), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintButton, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_BOOLEAN value; GB_INTEGER state; GB_BOOLEAN flat)
|
|
|
|
GET_COORD();
|
|
style_button(p, x, y, w, h, VARG(value), VARGOPT(state, GB_DRAW_STATE_NORMAL), VARGOPT(flat, FALSE));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintPanel, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_INTEGER border; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_panel(p, x, y, w, h, VARG(border), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintHandle, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_BOOLEAN vertical; GB_INTEGER state)
|
|
|
|
GET_COORD();
|
|
style_handle(p, x, y, w, h, VARGOPT(vertical, FALSE), VARGOPT(state, GB_DRAW_STATE_NORMAL));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_PaintBox, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h; GB_INTEGER state; GB_INTEGER color)
|
|
|
|
GET_COORD();
|
|
style_box(p, x, y, w, h, VARGOPT(state, GB_DRAW_STATE_NORMAL), VARGOPT(color, GB_COLOR_DEFAULT));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_StateOf, GB_OBJECT control)
|
|
|
|
CWIDGET *control = (CWIDGET *)VARG(control);
|
|
QWidget *widget;
|
|
int state;
|
|
bool design;
|
|
|
|
if (GB.CheckObject(control))
|
|
return;
|
|
|
|
widget = QWIDGET(control);
|
|
design = CWIDGET_is_design(control);
|
|
|
|
state = GB_DRAW_STATE_NORMAL;
|
|
if (!widget->isEnabled())
|
|
state |= GB_DRAW_STATE_DISABLED;
|
|
if (widget->hasFocus() && !design)
|
|
state |= GB_DRAW_STATE_FOCUS;
|
|
if (CWIDGET_is_visible(control) && control->flag.inside && !design)
|
|
state |= GB_DRAW_STATE_HOVER;
|
|
|
|
GB.ReturnInteger(state);
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_BackgroundOf, GB_OBJECT control)
|
|
|
|
CWIDGET *control = (CWIDGET *)VARG(control);
|
|
|
|
if (GB.CheckObject(control))
|
|
return;
|
|
|
|
GB.ReturnInteger(CWIDGET_get_real_background(control));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Style_ForegroundOf, GB_OBJECT control)
|
|
|
|
CWIDGET *control = (CWIDGET *)VARG(control);
|
|
|
|
if (GB.CheckObject(control))
|
|
return;
|
|
|
|
GB.ReturnInteger(CWIDGET_get_real_foreground(control));
|
|
|
|
END_METHOD
|
|
|
|
#if 0
|
|
BEGIN_METHOD(Style_FontOf, GB_OBJECT control)
|
|
|
|
CWIDGET *control = (CWIDGET *)VARG(control);
|
|
|
|
if (GB.CheckObject(control))
|
|
return;
|
|
|
|
GB.ReturnObject(CWIDGET_get_real_font(control));
|
|
|
|
END_METHOD
|
|
#endif
|
|
|
|
BEGIN_METHOD_VOID(Style_exit)
|
|
|
|
GB.FreeString(&_style_name);
|
|
|
|
END_METHOD
|
|
|
|
GB_DESC StyleDesc[] =
|
|
{
|
|
GB_DECLARE("Style", 0), GB_VIRTUAL_CLASS(),
|
|
|
|
GB_STATIC_METHOD("_exit", NULL, Style_exit, NULL),
|
|
|
|
GB_STATIC_PROPERTY_READ("ScrollbarSize", "i", Style_ScrollbarSize),
|
|
GB_STATIC_PROPERTY_READ("ScrollbarSpacing", "i", Style_ScrollbarSpacing),
|
|
GB_STATIC_PROPERTY_READ("FrameWidth", "i", Style_FrameWidth),
|
|
GB_STATIC_PROPERTY_READ("TextBoxFrameWidth", "i", Style_FrameWidth),
|
|
GB_STATIC_PROPERTY_READ("BoxFrameWidth", "i", Style_BoxFrameWidth),
|
|
GB_STATIC_PROPERTY_READ("BoxFrameHeight", "i", Style_BoxFrameWidth),
|
|
GB_STATIC_PROPERTY_READ("Name", "s", Style_Name),
|
|
|
|
GB_STATIC_METHOD("PaintArrow", NULL, Style_PaintArrow, "(X)i(Y)i(Width)i(Height)i(Type)i[(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintCheck", NULL, Style_PaintCheck, "(X)i(Y)i(Width)i(Height)i(Value)i[(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintOption", NULL, Style_PaintOption, "(X)i(Y)i(Width)i(Height)i(Value)b[(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintSeparator", NULL, Style_PaintSeparator, "(X)i(Y)i(Width)i(Height)i[(Vertical)b(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintButton", NULL, Style_PaintButton, "(X)i(Y)i(Width)i(Height)i(Value)b[(Flag)i(Flat)b]"),
|
|
GB_STATIC_METHOD("PaintPanel", NULL, Style_PaintPanel, "(X)i(Y)i(Width)i(Height)i(Border)i[(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintHandle", NULL, Style_PaintHandle, "(X)i(Y)i(Width)i(Height)i[(Vertical)b(Flag)i]"),
|
|
GB_STATIC_METHOD("PaintBox", NULL, Style_PaintBox, "(X)i(Y)i(Width)i(Height)i[(Flag)i(Color)i]"),
|
|
|
|
GB_CONSTANT("Normal", "i", GB_DRAW_STATE_NORMAL),
|
|
GB_CONSTANT("Disabled", "i", GB_DRAW_STATE_DISABLED),
|
|
GB_CONSTANT("HasFocus", "i", GB_DRAW_STATE_FOCUS),
|
|
GB_CONSTANT("Hovered", "i", GB_DRAW_STATE_HOVER),
|
|
GB_CONSTANT("Active", "i", GB_DRAW_STATE_ACTIVE),
|
|
|
|
GB_STATIC_METHOD("StateOf", "i", Style_StateOf, "(Control)Control;"),
|
|
GB_STATIC_METHOD("BackgroundOf", "i", Style_BackgroundOf, "(Control)Control;"),
|
|
GB_STATIC_METHOD("ForegroundOf", "i", Style_ForegroundOf, "(Control)Control;"),
|
|
//GB_STATIC_METHOD("FontOf", "Font", Style_FontOf, "(Control)Control;"),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|