/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <osl/module.h>
#include <config_cairo_canvas.h>
#include <unx/gtk/gtkframe.hxx>
#include <unx/gtk/gtkdata.hxx>
#include <unx/gtk/gtkinst.hxx>
#include <unx/gtk/gtkgdi.hxx>
#include <unx/gtk/gtkbackend.hxx>
#include <vcl/BitmapTools.hxx>
#include <vcl/CairoFormats.hxx>
#include <vcl/decoview.hxx>
#include <vcl/settings.hxx>
#include <unx/fontmanager.hxx>
#include <o3tl/string_view.hxx>
#include <scrollbarvalue.hxx>
#include <IconThemeSelector.hxx>
#include "custom-theme.hxx"
#include <vcl/themecolors.hxx>
#include "gtkcairo.hxx"
GtkCssProvider* GtkSalGraphics::mpCustomThemeProvider = nullptr;
GtkStyleContext* GtkSalGraphics::mpWindowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpLinkButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpEntryStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpTextViewStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpVScrollbarStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpVScrollbarContentsStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpVScrollbarTroughStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpVScrollbarSliderStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpVScrollbarButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpHScrollbarStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpHScrollbarContentsStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpHScrollbarTroughStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpHScrollbarSliderStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpHScrollbarButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpToolbarStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpToolButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpToolbarSeparatorStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpCheckButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpCheckButtonCheckStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpRadioButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpRadioButtonRadioStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSpinStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSpinUpStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSpinDownStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxEntryStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonArrowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonBoxStyle= nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonArrowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFrameInStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFrameOutStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFixedHoriLineStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFixedVertLineStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpTreeHeaderButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpProgressBarStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpProgressBarTroughStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpProgressBarProgressStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookStackStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabLabelStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabActiveLabelStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabHoverLabelStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuBarStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuBarItemStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuWindowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuItemStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuItemArrowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpMenuItemLabelStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpCheckMenuItemStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpCheckMenuItemCheckStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpRadioMenuItemStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpRadioMenuItemRadioStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemSeparatorStyle = nullptr;
gint GtkSalGraphics::mnVerticalSeparatorMinWidth = 0;
#if !GTK_CHECK_VERSION(4, 0, 0)
static void style_context_get_margin(GtkStyleContext *pContext, GtkBorder *pMargin)
{
#if GTK_CHECK_VERSION(4, 0, 0)
gtk_style_context_get_margin(pContext, pMargin);
#else
gtk_style_context_get_margin(pContext, gtk_style_context_get_state(pContext), pMar
gin);
#endif
}
#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
static void style_context_get_border(GtkStyleContext* pContext, GtkBorder* pBorder)
{
#if GTK_CHECK_VERSION(4, 0, 0)
gtk_style_context_get_border(pContext, pBorder);
#else
gtk_style_context_get_border(pContext, gtk_style_context_get_state(pContext), pBorder);
#endif
}
#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
static void style_context_get_padding(GtkStyleContext* pContext, GtkBorder* pPadding)
{
#if GTK_CHECK_VERSION(4, 0, 0)
gtk_style_context_get_padding(pContext, pPadding);
#else
gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), pPadding);
#endif
}
#endif
bool GtkSalGraphics::style_loaded = false ;
/************************************************************************
* State conversion
************************************************************************/
#if !GTK_CHECK_VERSION(4, 0, 0)
static GtkStateFlags NWConvertVCLStateToGTKState(ControlState nVCLState)
{
GtkStateFlags nGTKState = GTK_STATE_FLAG_NORMAL;
if (!( nVCLState & ControlState::ENABLED ))
{
nGTKState = GTK_STATE_FLAG_INSENSITIVE;
}
if ( nVCLState & ControlState::PRESSED )
{
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_ACTIVE);
}
if ( nVCLState & ControlState::ROLLOVER )
{
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_PRELIGHT);
}
if ( nVCLState & ControlState::SELECTED )
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_SELECTED);
if ( nVCLState & ControlState::FOCUSED )
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_FOCUSED);
if (AllSettings::GetLayoutRTL())
{
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_RTL);
}
else
{
nGTKState = static_cast <GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_LTR);
}
return nGTKState;
}
namespace {
enum class RenderType {
BackgroundAndFrame = 1,
Check,
Background,
MenuSeparator,
ToolbarSeparator,
Separator,
Arrow,
Radio,
Scrollbar,
Spinbutton,
Combobox,
Expander,
Icon,
Progress,
TabItem,
Focus
};
}
static void NWCalcArrowRect( const tools::Rectangle& rButton, tools::Rectangle& rArrow )
{
// Size the arrow appropriately
Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
rArrow.SetSize( aSize );
rArrow.SetPos( Point(
rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2,
rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
) );
}
tools::Rectangle GtkSalGraphics::NWGetSpinButtonRect( ControlPart nPart, tools::Rectangle aAreaRect)
{
gint w, h;
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
gint icon_size = std::max(w, h);
GtkBorder padding, border;
style_context_get_padding(mpSpinUpStyle, &padding);
style_context_get_border(mpSpinUpStyle, &border);
gint buttonWidth = icon_size + padding.left + padding.right +
border.left + border.right;
tools::Rectangle buttonRect(Point(0, aAreaRect.Top()), Size(buttonWidth, 0));
buttonRect.setHeight(aAreaRect.GetHeight());
tools::Rectangle partRect(buttonRect);
if ( nPart == ControlPart::ButtonUp )
{
if (AllSettings::GetLayoutRTL())
partRect.SetPosX(aAreaRect.Left());
else
partRect.SetPosX(aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()));
}
else if ( nPart == ControlPart::ButtonDown )
{
if (AllSettings::GetLayoutRTL())
partRect.SetPosX(aAreaRect.Left() + buttonRect.GetWidth());
else
partRect.SetPosX(aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth()));
}
else
{
if (AllSettings::GetLayoutRTL())
{
partRect.SetRight( aAreaRect.Left() + aAreaRect.GetWidth() );
partRect.SetLeft( aAreaRect.Left() + (2 * buttonRect.GetWidth()) - 1 );
}
else
{
partRect.SetRight( (aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth())) - 1 );
partRect.SetLeft( aAreaRect.Left() );
}
partRect.SetTop( aAreaRect.Top() );
partRect.SetBottom( aAreaRect.Bottom() );
}
return partRect;
}
#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
namespace
{
void QuerySize(GtkStyleContext *pContext, Size &rSize)
{
GtkBorder margin, border, padding;
style_context_get_margin(pContext, &margin);
style_context_get_border(pContext, &border);
style_context_get_padding(pContext, &padding);
int nMinWidth(0), nMinHeight(0);
GtkStateFlags stateflags = gtk_style_context_get_state (pContext);
gtk_style_context_get(pContext, stateflags,
"min-width" , &nMinWidth, "min-height" , &nMinHeight, nullptr);
nMinWidth += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
nMinHeight += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
rSize = Size(std::max<tools::Long >(rSize.Width(), nMinWidth), std::max<tools::Long >(rSize.Height(), nMinHeight));
}
}
#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
tools::Rectangle GtkSalGraphics::NWGetScrollButtonRect( ControlPart nPart, tools::Rectangle aAreaRect )
{
tools::Rectangle buttonRect;
gboolean has_forward;
gboolean has_forward2;
gboolean has_backward;
gboolean has_backward2;
GtkStyleContext* pScrollbarStyle = nullptr;
if ((nPart == ControlPart::ButtonLeft) || (nPart == ControlPart::ButtonRight))
pScrollbarStyle = mpHScrollbarStyle;
else // (nPart == ControlPart::ButtonUp) || (nPart == ControlPart::ButtonDown)
pScrollbarStyle = mpVScrollbarStyle;
gtk_style_context_get_style( pScrollbarStyle,
"has-forward-stepper" , &has_forward,
"has-secondary-forward-stepper" , &has_forward2,
"has-backward-stepper" , &has_backward,
"has-secondary-backward-stepper" , &has_backward2, nullptr );
gint nFirst = 0;
gint nSecond = 0;
if ( has_forward ) nSecond += 1;
if ( has_forward2 ) nFirst += 1;
if ( has_backward ) nFirst += 1;
if ( has_backward2 ) nSecond += 1;
Size aSize;
if (nPart == ControlPart::ButtonLeft || nPart == ControlPart::ButtonRight)
{
QuerySize(mpHScrollbarStyle, aSize);
QuerySize(mpHScrollbarContentsStyle, aSize);
QuerySize(mpHScrollbarButtonStyle, aSize);
}
else
{
QuerySize(mpVScrollbarStyle, aSize);
QuerySize(mpVScrollbarContentsStyle, aSize);
QuerySize(mpVScrollbarButtonStyle, aSize);
}
if (nPart == ControlPart::ButtonUp)
{
aSize.setHeight( aSize.Height() * nFirst );
buttonRect.SetLeft(aAreaRect.Left());
buttonRect.SetTop(aAreaRect.Top());
}
else if (nPart == ControlPart::ButtonLeft)
{
aSize.setWidth( aSize.Width() * nFirst );
buttonRect.SetLeft(aAreaRect.Left());
buttonRect.SetTop(aAreaRect.Top());
}
else if (nPart == ControlPart::ButtonDown)
{
aSize.setHeight( aSize.Height() * nSecond );
buttonRect.SetLeft(aAreaRect.Left());
buttonRect.SetTop(aAreaRect.Top() + aAreaRect.GetHeight() - aSize.Height());
}
else if (nPart == ControlPart::ButtonRight)
{
aSize.setWidth( aSize.Width() * nSecond );
buttonRect.SetLeft(aAreaRect.Left() + aAreaRect.GetWidth() - aSize.Width());
buttonRect.SetTop(aAreaRect.Top());
}
buttonRect.SetSize(aSize);
return buttonRect;
}
#endif
static GtkWidget* gCacheWindow;
static GtkWidget* gDumbContainer;
#if GTK_CHECK_VERSION(4, 0, 0)
static GtkWidget* gVScrollbar;
static GtkWidget* gTextView;
#else
static GtkWidget* gComboBox;
static GtkWidget* gListBox;
static GtkWidget* gSpinBox;
static GtkWidget* gTreeViewWidget;
#endif
static GtkWidget* gHScrollbar;
static GtkWidget* gEntryBox;
namespace
{
void style_context_set_state(GtkStyleContext* context, GtkStateFlags flags)
{
#if !GTK_CHECK_VERSION(4, 0, 0)
do
{
gtk_style_context_set_state(context, flags);
}
while ((context = gtk_style_context_get_parent(context)));
#else
gtk_style_context_set_state(context, flags);
#endif
}
class StyleContextSave
{
private :
std::vector<std::pair<GtkStyleContext*, GtkStateFlags>> m_aStates;
public :
void save(GtkStyleContext* context)
{
#if !GTK_CHECK_VERSION(4, 0, 0)
do
{
m_aStates.emplace_back(context, gtk_style_context_get_state(context));
}
while ((context = gtk_style_context_get_parent(context)));
#else
m_aStates.emplace_back(context, gtk_style_context_get_state(context));
#endif
}
void restore()
{
for (auto a = m_aStates.rbegin(); a != m_aStates.rend(); ++a)
{
gtk_style_context_set_state(a->first, a->second);
}
m_aStates.clear();
}
};
#if !GTK_CHECK_VERSION(4, 0, 0)
tools::Rectangle render_common(GtkStyleContext *pContext, cairo_t *cr, const tools::Rectangle &rIn, GtkStateFlags flags)
{
if (!pContext)
return rIn;
gtk_style_context_set_state(pContext, flags);
tools::Rectangle aRect(rIn);
GtkBorder margin;
style_context_get_margin(pContext, &margin);
aRect.AdjustLeft(margin.left );
aRect.AdjustTop(margin.top );
aRect.AdjustRight( -(margin.right) );
aRect.AdjustBottom( -(margin.bottom) );
gtk_render_background(pContext, cr, aRect.Left(), aRect.Top(),
aRect.GetWidth(), aRect.GetHeight());
gtk_render_frame(pContext, cr, aRect.Left(), aRect.Top(),
aRect.GetWidth(), aRect.GetHeight());
GtkBorder border, padding;
style_context_get_border(pContext, &border);
style_context_get_padding(pContext, &padding);
aRect.AdjustLeft(border.left + padding.left );
aRect.AdjustTop(border.top + padding.top );
aRect.AdjustRight( -(border.right + padding.right) );
aRect.AdjustBottom( -(border.bottom + padding.bottom) );
return aRect;
}
#endif
}
#if !GTK_CHECK_VERSION(4, 0, 0)
void GtkSalGraphics::PaintScrollbar(GtkStyleContext *context,
cairo_t *cr,
const tools::Rectangle& rControlRectangle,
ControlPart nPart,
const ImplControlValue& rValue )
{
assert(rValue.getType() == ControlType::Scrollbar);
const ScrollbarValue& rScrollbarVal = static_cast <const ScrollbarValue&>(rValue);
tools::Rectangle scrollbarRect;
GtkStateFlags stateFlags;
GtkOrientation scrollbarOrientation;
tools::Rectangle thumbRect = rScrollbarVal.maThumbRect;
tools::Rectangle button11BoundRect = rScrollbarVal.maButton1Rect; // backward
tools::Rectangle button22BoundRect = rScrollbarVal.maButton2Rect; // forward
tools::Rectangle button12BoundRect = rScrollbarVal.maButton1Rect; // secondary forward
tools::Rectangle button21BoundRect = rScrollbarVal.maButton2Rect; // secondary backward
gdouble arrow1Angle; // backward
gdouble arrow2Angle; // forward
tools::Rectangle arrowRect;
gint slider_width = 0;
gint stepper_size = 0;
// make controlvalue rectangles relative to area
thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
// Find the overall bounding rect of the control
scrollbarRect = rControlRectangle;
if (scrollbarRect.IsEmpty())
return ;
gint slider_side;
Size aSize;
if (nPart == ControlPart::DrawBackgroundHorz)
{
QuerySize(mpHScrollbarStyle, aSize);
QuerySize(mpHScrollbarContentsStyle, aSize);
QuerySize(mpHScrollbarTroughStyle, aSize);
QuerySize(mpHScrollbarSliderStyle, aSize);
slider_side = aSize.Height();
gtk_style_context_get(mpHScrollbarButtonStyle,
gtk_style_context_get_state(mpHScrollbarButtonStyle),
"min-height" , &slider_width,
"min-width" , &stepper_size, nullptr);
}
else
{
QuerySize(mpVScrollbarStyle, aSize);
QuerySize(mpVScrollbarContentsStyle, aSize);
QuerySize(mpVScrollbarTroughStyle, aSize);
QuerySize(mpVScrollbarSliderStyle, aSize);
slider_side = aSize.Width();
gtk_style_context_get(mpVScrollbarButtonStyle,
gtk_style_context_get_state(mpVScrollbarButtonStyle),
"min-width" , &slider_width,
"min-height" , &stepper_size, nullptr);
}
gboolean has_forward;
gboolean has_forward2;
gboolean has_backward;
gboolean has_backward2;
gtk_style_context_get_style( context,
"has-forward-stepper" , &has_forward,
"has-secondary-forward-stepper" , &has_forward2,
"has-backward-stepper" , &has_backward,
"has-secondary-backward-stepper" , &has_backward2, nullptr );
if ( nPart == ControlPart::DrawBackgroundHorz )
{
// Center vertically in the track
scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
thumbRect.SetSize( Size( thumbRect.GetWidth(), slider_side ) );
scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
arrow1Angle = G_PI * 3 / 2;
arrow2Angle = G_PI / 2;
if ( has_backward )
{
button12BoundRect.Move( stepper_size,
(scrollbarRect.GetHeight() - slider_width) / 2 );
}
button11BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
if ( has_backward2 )
{
button22BoundRect.Move( stepper_size, (scrollbarRect.GetHeight() - slider_width) / 2 );
button21BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
}
else
{
button22BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
}
button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
}
else
{
// Center horizontally in the track
scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
thumbRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
thumbRect.SetSize( Size( slider_side, thumbRect.GetHeight() ) );
scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
arrow1Angle = 0;
arrow2Angle = G_PI;
if ( has_backward )
{
button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
stepper_size );
}
button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
if ( has_backward2 )
{
button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size );
button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
}
else
{
button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
}
button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
}
bool has_slider = !thumbRect.IsEmpty();
// ----------------- CONTENTS
GtkStyleContext* pScrollbarContentsStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
gtk_render_background(gtk_widget_get_style_context(gCacheWindow), cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
gtk_render_background(context, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
gtk_render_frame(context, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
gtk_render_background(pScrollbarContentsStyle, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
gtk_render_frame(pScrollbarContentsStyle, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
bool backwardButtonInsensitive =
rScrollbarVal.mnCur == rScrollbarVal.mnMin;
bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
// ----------------- BUTTON 1
if ( has_backward )
{
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
if ( backwardButtonInsensitive )
stateFlags = GTK_STATE_FLAG_INSENSITIVE;
GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
gtk_render_background(pScrollbarButtonStyle, cr,
button11BoundRect.Left(), button11BoundRect.Top(),
button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
gtk_render_frame(pScrollbarButtonStyle, cr,
button11BoundRect.Left(), button11BoundRect.Top(),
button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
// ----------------- ARROW 1
NWCalcArrowRect( button11BoundRect, arrowRect );
gtk_render_arrow(pScrollbarButtonStyle, cr,
arrow1Angle,
arrowRect.Left(), arrowRect.Top(),
MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
}
if ( has_forward2 )
{
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
if ( forwardButtonInsensitive )
stateFlags = GTK_STATE_FLAG_INSENSITIVE;
GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
gtk_render_background(pScrollbarButtonStyle, cr,
button12BoundRect.Left(), button12BoundRect.Top(),
button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
gtk_render_frame(pScrollbarButtonStyle, cr,
button12BoundRect.Left(), button12BoundRect.Top(),
button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
// ----------------- ARROW 1
NWCalcArrowRect( button12BoundRect, arrowRect );
gtk_render_arrow(pScrollbarButtonStyle, cr,
arrow2Angle,
arrowRect.Left(), arrowRect.Top(),
MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
}
// ----------------- BUTTON 2
if ( has_forward )
{
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
if ( forwardButtonInsensitive )
stateFlags = GTK_STATE_FLAG_INSENSITIVE;
GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
gtk_render_background(pScrollbarButtonStyle, cr,
button22BoundRect.Left(), button22BoundRect.Top(),
button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
gtk_render_frame(pScrollbarButtonStyle, cr,
button22BoundRect.Left(), button22BoundRect.Top(),
button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
// ----------------- ARROW 2
NWCalcArrowRect( button22BoundRect, arrowRect );
gtk_render_arrow(pScrollbarButtonStyle, cr,
arrow2Angle,
arrowRect.Left(), arrowRect.Top(),
MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
}
if ( has_backward2 )
{
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
if ( backwardButtonInsensitive )
stateFlags = GTK_STATE_FLAG_INSENSITIVE;
GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
gtk_render_background(pScrollbarButtonStyle, cr,
button21BoundRect.Left(), button21BoundRect.Top(),
button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
gtk_render_frame(pScrollbarButtonStyle, cr,
button21BoundRect.Left(), button21BoundRect.Top(),
button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
// ----------------- ARROW 2
NWCalcArrowRect( button21BoundRect, arrowRect );
gtk_render_arrow(pScrollbarButtonStyle, cr,
arrow1Angle,
arrowRect.Left(), arrowRect.Top(),
MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
}
// ----------------- TROUGH
// trackrect matches that of ScrollBar::ImplCalc
tools::Rectangle aTrackRect(Point(0, 0), scrollbarRect.GetSize());
if (nPart == ControlPart::DrawBackgroundHorz)
{
tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonLeft, aTrackRect);
tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonRight, aTrackRect);
if (!aBtn1Rect.IsWidthEmpty())
aTrackRect.SetLeft( aBtn1Rect.Right() );
if (!aBtn2Rect.IsWidthEmpty())
aTrackRect.SetRight( aBtn2Rect.Left() );
}
else
{
tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonUp, aTrackRect);
tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonDown, aTrackRect);
if (!aBtn1Rect.IsHeightEmpty())
aTrackRect.SetTop( aBtn1Rect.Bottom() + 1 );
if (!aBtn2Rect.IsHeightEmpty())
aTrackRect.SetBottom( aBtn2Rect.Top() );
}
GtkStyleContext* pScrollbarTroughStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
gtk_render_background(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
aTrackRect.GetWidth(), aTrackRect.GetHeight() );
gtk_render_frame(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
aTrackRect.GetWidth(), aTrackRect.GetHeight() );
// ----------------- THUMB
if ( !has_slider )
return ;
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnThumbState);
if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
stateFlags = static_cast <GtkStateFlags>(stateFlags | GTK_STATE_FLAG_PRELIGHT);
GtkStyleContext* pScrollbarSliderStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarSliderStyle : mpHScrollbarSliderStyle;
gtk_style_context_set_state(pScrollbarSliderStyle, stateFlags);
GtkBorder margin;
style_context_get_margin(pScrollbarSliderStyle, &margin);
gtk_render_background(pScrollbarSliderStyle, cr,
thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
thumbRect.GetWidth() - margin.left - margin.right,
thumbRect.GetHeight() - margin.top - margin.bottom);
gtk_render_frame(pScrollbarSliderStyle, cr,
thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
thumbRect.GetWidth() - margin.left - margin.right,
thumbRect.GetHeight() - margin.top - margin.bottom);
}
void GtkSalGraphics::PaintOneSpinButton( GtkStyleContext *context,
cairo_t *cr,
ControlPart nPart,
tools::Rectangle aAreaRect,
ControlState nState )
{
GtkBorder padding, border;
GtkStateFlags stateFlags = NWConvertVCLStateToGTKState(nState);
tools::Rectangle buttonRect = NWGetSpinButtonRect( nPart, aAreaRect );
gtk_style_context_set_state(context, stateFlags);
style_context_get_padding(context, &padding);
style_context_get_border(context, &border);
gtk_render_background(context, cr,
buttonRect.Left(), buttonRect.Top(),
buttonRect.GetWidth(), buttonRect.GetHeight() );
gint iconWidth = buttonRect.GetWidth() - padding.left - padding.right - border.left - border.right;
gint iconHeight = buttonRect.GetHeight() - padding.top - padding.bottom - border.top - border.bottom;
const char * icon = (nPart == ControlPart::ButtonUp) ? "list-add-symbolic" : "list-remove-symbolic" ;
GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
gint scale = gtk_style_context_get_scale (context);
GtkIconInfo *info = gtk_icon_theme_lookup_icon_for_scale(pIconTheme, icon, std::min(iconWidth, iconHeight), scale,
static_cast <GtkIconLookupFlags>(0));
GdkPixbuf *pixbuf = gtk_icon_info_load_symbolic_for_context(info, context, nullptr, nullptr);
g_object_unref(info);
iconWidth = gdk_pixbuf_get_width(pixbuf)/scale;
iconHeight = gdk_pixbuf_get_height(pixbuf)/scale;
tools::Rectangle arrowRect(buttonRect.Center() - Point(iconWidth / 2, iconHeight / 2),
Size(iconWidth, iconHeight));
gtk_style_context_save (context);
gtk_style_context_set_scale (context, 1);
gtk_render_icon(context, cr, pixbuf, arrowRect.Left(), arrowRect.Top());
gtk_style_context_restore (context);
g_object_unref(pixbuf);
gtk_render_frame(context, cr,
buttonRect.Left(), buttonRect.Top(),
buttonRect.GetWidth(), buttonRect.GetHeight() );
}
void GtkSalGraphics::PaintSpinButton(GtkStateFlags flags,
cairo_t *cr,
const tools::Rectangle& rControlRectangle,
ControlPart nPart,
const ImplControlValue& rValue )
{
const SpinbuttonValue *pSpinVal = (rValue.getType() == ControlType::SpinButtons) ? static_cast <const SpinbuttonValue *>(&rValue) : nullptr;
ControlPart upBtnPart = ControlPart::ButtonUp;
ControlState upBtnState = ControlState::NONE;
ControlPart downBtnPart = ControlPart::ButtonDown;
ControlState downBtnState = ControlState::NONE;
if ( pSpinVal )
{
upBtnPart = pSpinVal->mnUpperPart;
upBtnState = pSpinVal->mnUpperState;
downBtnPart = pSpinVal->mnLowerPart;
downBtnState = pSpinVal->mnLowerState;
}
if (nPart == ControlPart::Entire)
{
gtk_style_context_set_state(mpWindowStyle, flags);
gtk_render_background(mpWindowStyle, cr,
0, 0,
rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
gtk_style_context_set_state(mpSpinStyle, flags);
gtk_render_background(mpSpinStyle, cr,
0, 0,
rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
}
cairo_translate(cr, -rControlRectangle.Left(), -rControlRectangle.Top());
PaintOneSpinButton(mpSpinUpStyle, cr, upBtnPart, rControlRectangle, upBtnState );
PaintOneSpinButton(mpSpinDownStyle, cr, downBtnPart, rControlRectangle, downBtnState );
cairo_translate(cr, rControlRectangle.Left(), rControlRectangle.Top());
if (nPart == ControlPart::Entire)
{
gtk_render_frame(mpSpinStyle, cr,
0, 0,
rControlRectangle.GetWidth(), rControlRectangle.GetHeight() );
}
}
#define FALLBACK_ARROW_SIZE gint(11 * 0.85)
tools::Rectangle GtkSalGraphics::NWGetComboBoxButtonRect(ControlType nType,
ControlPart nPart,
tools::Rectangle aAreaRect )
{
tools::Rectangle aButtonRect;
GtkBorder padding;
if (nType == ControlType::Listbox)
style_context_get_padding(mpListboxButtonStyle, &padding);
else
style_context_get_padding(mpButtonStyle, &padding);
gint nArrowWidth = FALLBACK_ARROW_SIZE;
gtk_style_context_get(mpComboboxButtonArrowStyle,
gtk_style_context_get_state(mpComboboxButtonArrowStyle),
"min-width" , &nArrowWidth, nullptr);
gint nButtonWidth = nArrowWidth + padding.left + padding.right;
if ( nPart == ControlPart::ButtonDown )
{
Point aPos(aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, aAreaRect.Top());
if (AllSettings::GetLayoutRTL())
aPos.setX( aAreaRect.Left() );
aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
aButtonRect.SetPos(aPos);
}
else if ( nPart == ControlPart::SubEdit )
{
gint adjust_left = padding.left;
gint adjust_top = padding.top;
gint adjust_right = padding.right;
gint adjust_bottom = padding.bottom;
aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - (adjust_left + adjust_right),
aAreaRect.GetHeight() - (adjust_top + adjust_bottom)) );
Point aEditPos = aAreaRect.TopLeft();
if (AllSettings::GetLayoutRTL())
aEditPos.AdjustX(nButtonWidth );
else
aEditPos.AdjustX(adjust_left );
aEditPos.AdjustY(adjust_top );
aButtonRect.SetPos( aEditPos );
}
return aButtonRect;
}
void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
const tools::Rectangle& rControlRectangle,
ControlType nType,
ControlPart nPart )
{
tools::Rectangle areaRect;
tools::Rectangle buttonRect;
tools::Rectangle arrowRect;
// Find the overall bounding rect of the buttons's drawing area,
// plus its actual draw rect excluding adornment
areaRect = rControlRectangle;
buttonRect = NWGetComboBoxButtonRect(ControlType::Combobox, ControlPart::ButtonDown, areaRect);
tools::Rectangle aEditBoxRect( areaRect );
aEditBoxRect.SetSize( Size( areaRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
if (AllSettings::GetLayoutRTL())
aEditBoxRect.SetPos( Point( areaRect.Left() + buttonRect.GetWidth(), areaRect.Top() ) );
gint arrow_width = FALLBACK_ARROW_SIZE, arrow_height = FALLBACK_ARROW_SIZE;
if (nType == ControlType::Combobox)
{
gtk_style_context_get(mpComboboxButtonArrowStyle,
gtk_style_context_get_state(mpComboboxButtonArrowStyle),
"min-width" , &arrow_width, "min-height" , &arrow_height, nullptr);
}
else if (nType == ControlType::Listbox)
{
gtk_style_context_get(mpListboxButtonArrowStyle,
gtk_style_context_get_state(mpListboxButtonArrowStyle),
"min-width" , &arrow_width, "min-height" , &arrow_height, nullptr);
}
arrowRect.SetSize(Size(arrow_width, arrow_height));
arrowRect.SetPos( Point( buttonRect.Left() + static_cast <gint>((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
buttonRect.Top() + static_cast <gint>((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
tools::Rectangle aRect(Point(0, 0), Size(areaRect.GetWidth(), areaRect.GetHeight()));
if (nType == ControlType::Combobox)
{
if ( nPart == ControlPart::Entire )
{
render_common(mpComboboxStyle, cr, aRect, flags);
render_common(mpComboboxBoxStyle, cr, aRect, flags);
tools::Rectangle aEntryRect(Point(aEditBoxRect.Left() - areaRect.Left(),
aEditBoxRect.Top() - areaRect.Top()),
Size(aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight()));
GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxEntryStyle);
if (AllSettings::GetLayoutRTL())
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_LEFT);
else
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_RIGHT);
render_common(mpComboboxEntryStyle, cr, aEntryRect, flags);
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, eJuncSides);
}
tools::Rectangle aButtonRect(Point(buttonRect.Left() - areaRect.Left(), buttonRect.Top() - areaRect.Top()),
Size(buttonRect.GetWidth(), buttonRect.GetHeight()));
GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxButtonStyle);
if (AllSettings::GetLayoutRTL())
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_RIGHT);
else
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_LEFT);
render_common(mpComboboxButtonStyle, cr, aButtonRect, flags);
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, eJuncSides);
gtk_render_arrow(mpComboboxButtonArrowStyle, cr,
G_PI,
(arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
arrowRect.GetWidth() );
}
else if (nType == ControlType::Listbox)
{
if ( nPart == ControlPart::ListboxWindow )
{
/* render the popup window with the menu style */
gtk_render_frame(mpMenuStyle, cr,
0, 0,
areaRect.GetWidth(), areaRect.GetHeight());
}
else
{
render_common(mpListboxStyle, cr, aRect, flags);
render_common(mpListboxButtonStyle, cr, aRect, flags);
render_common(mpListboxBoxStyle, cr, aRect, flags);
gtk_render_arrow(mpListboxButtonArrowStyle, cr,
G_PI,
(arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
arrowRect.GetWidth() );
}
}
}
static void appendComboEntry(GtkWidgetPath* pSiblingsPath)
{
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_ENTRY);
gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "entry" );
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo" );
}
static void appendComboButton(GtkWidgetPath* pSiblingsPath)
{
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "button" );
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo" );
}
static GtkWidgetPath* buildLTRComboSiblingsPath()
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboEntry(pSiblingsPath);
appendComboButton(pSiblingsPath);
return pSiblingsPath;
}
static GtkWidgetPath* buildRTLComboSiblingsPath()
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboButton(pSiblingsPath);
appendComboEntry(pSiblingsPath);
return pSiblingsPath;
}
GtkStyleContext* GtkSalGraphics::makeContext(GtkWidgetPath *pPath, GtkStyleContext *pParent)
{
GtkStyleContext* context = gtk_style_context_new();
gtk_style_context_set_screen(context, gtk_widget_get_screen(mpWindow));
gtk_style_context_set_path(context, pPath);
if (pParent == nullptr)
{
GtkWidget* pTopLevel = widget_get_toplevel(mpWindow);
GtkStyleContext* pStyle = gtk_widget_get_style_context(pTopLevel);
gtk_style_context_set_parent(context, pStyle);
gtk_style_context_set_scale (context, gtk_style_context_get_scale (pStyle));
}
else
{
gtk_style_context_set_parent(context, pParent);
gtk_style_context_set_scale (context, gtk_style_context_get_scale (pParent));
}
gtk_widget_path_unref(pPath);
return context;
}
GtkStyleContext* GtkSalGraphics::createStyleContext(GtkControlPart ePart)
{
switch (ePart)
{
case GtkControlPart::ToplevelWindow:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "window" );
gtk_widget_path_iter_add_class(path, -1, "background" );
return makeContext(path, nullptr);
}
case GtkControlPart::Button:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "button" );
return makeContext(path, nullptr);
}
case GtkControlPart::LinkButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "button" );
gtk_widget_path_iter_add_class(path, -1, "link" );
return makeContext(path, nullptr);
}
case GtkControlPart::CheckButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "checkbutton" );
return makeContext(path, nullptr);
}
case GtkControlPart::CheckButtonCheck:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckButtonStyle));
gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "check" );
return makeContext(path, mpCheckButtonStyle);
}
case GtkControlPart::RadioButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "radiobutton" );
return makeContext(path, nullptr);
}
case GtkControlPart::RadioButtonRadio:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioButtonStyle));
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "radio" );
return makeContext(path, mpRadioButtonStyle);
}
case GtkControlPart::ComboboxBoxButtonBoxArrow:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonBoxStyle));
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "arrow" );
return makeContext(path, mpComboboxButtonBoxStyle);
}
case GtkControlPart::ListboxBoxButtonBoxArrow:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonBoxStyle));
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "arrow" );
return makeContext(path, mpListboxButtonBoxStyle);
}
case GtkControlPart::Entry:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
gtk_widget_path_iter_set_object_name(path, -1, "entry" );
return makeContext(path, nullptr);
}
case GtkControlPart::Combobox:
case GtkControlPart::Listbox:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "combobox" );
return makeContext(path, nullptr);
}
case GtkControlPart::ComboboxBox:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "box" );
gtk_widget_path_iter_add_class(path, -1, "horizontal" );
gtk_widget_path_iter_add_class(path, -1, "linked" );
return makeContext(path, mpComboboxStyle);
}
case GtkControlPart::ListboxBox:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "box" );
gtk_widget_path_iter_add_class(path, -1, "horizontal" );
gtk_widget_path_iter_add_class(path, -1, "linked" );
return makeContext(path, mpListboxStyle);
}
case GtkControlPart::ComboboxBoxEntry:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
GtkWidgetPath* pSiblingsPath;
if (AllSettings::GetLayoutRTL())
{
pSiblingsPath = buildRTLComboSiblingsPath();
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath();
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
}
gtk_widget_path_unref(pSiblingsPath);
return makeContext(path, mpComboboxBoxStyle);
}
case GtkControlPart::ComboboxBoxButton:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
GtkWidgetPath* pSiblingsPath;
if (AllSettings::GetLayoutRTL())
{
pSiblingsPath = buildRTLComboSiblingsPath();
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath();
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
}
gtk_widget_path_unref(pSiblingsPath);
return makeContext(path, mpComboboxBoxStyle);
}
case GtkControlPart::ListboxBoxButton:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxBoxStyle));
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "button" );
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo" );
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
gtk_widget_path_unref(pSiblingsPath);
return makeContext(path, mpListboxBoxStyle);
}
case GtkControlPart::ComboboxBoxButtonBox:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "box" );
gtk_widget_path_iter_add_class(path, -1, "horizontal" );
return makeContext(path, mpComboboxButtonStyle);
}
case GtkControlPart::ListboxBoxButtonBox:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "box" );
gtk_widget_path_iter_add_class(path, -1, "horizontal" );
return makeContext(path, mpListboxButtonStyle);
}
case GtkControlPart::SpinButton:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "spinbutton" );
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
return makeContext(path, mpWindowStyle);
}
case GtkControlPart::SpinButtonUpButton:
case GtkControlPart::SpinButtonDownButton:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSpinStyle));
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
gtk_widget_path_iter_set_object_name(path, -1, "button" );
gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::SpinButtonUpButton ? "up" : "down" );
return makeContext(path, mpSpinStyle);
}
case GtkControlPart::ScrollbarVertical:
case GtkControlPart::ScrollbarHorizontal:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
gtk_widget_path_iter_set_object_name(path, -1, "scrollbar" );
gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::ScrollbarVertical ? "vertical" : "horizontal" );
return makeContext(path, nullptr);
}
case GtkControlPart::ScrollbarVerticalContents:
case GtkControlPart::ScrollbarHorizontalContents:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ScrollbarVerticalContents) ? mpVScrollbarStyle : mpHScrollbarStyle;
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
gtk_widget_path_iter_set_object_name(path, -1, "contents" );
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarVerticalTrough:
case GtkControlPart::ScrollbarHorizontalTrough:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ScrollbarVerticalTrough) ? mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
gtk_widget_path_iter_set_object_name(path, -1, "trough" );
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarVerticalSlider:
case GtkControlPart::ScrollbarHorizontalSlider:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ScrollbarVerticalSlider) ? mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
gtk_widget_path_iter_set_object_name(path, -1, "slider" );
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarVerticalButton:
case GtkControlPart::ScrollbarHorizontalButton:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ScrollbarVerticalButton) ? mpVScrollbarStyle : mpHScrollbarStyle;
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
gtk_widget_path_iter_set_object_name(path, -1, "button" );
return makeContext(path, pParent);
}
case GtkControlPart::ProgressBar:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
gtk_widget_path_iter_set_object_name(path, -1, "progressbar" );
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
return makeContext(path, nullptr);
}
case GtkControlPart::ProgressBarTrough:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarStyle));
gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
gtk_widget_path_iter_set_object_name(path, -1, "trough" );
return makeContext(path, mpProgressBarStyle);
}
case GtkControlPart::ProgressBarProgress:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarTroughStyle));
gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
gtk_widget_path_iter_set_object_name(path, -1, "progress" );
return makeContext(path, mpProgressBarTroughStyle);
}
case GtkControlPart::Notebook:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
gtk_widget_path_iter_set_object_name(path, -1, "notebook" );
return makeContext(path, mpWindowStyle);
}
case GtkControlPart::NotebookStack:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
gtk_widget_path_iter_set_object_name(path, -1, "stack" );
return makeContext(path, mpNotebookStyle);
}
case GtkControlPart::NotebookHeader:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
gtk_widget_path_iter_set_object_name(path, -1, "header" );
gtk_widget_path_iter_add_class(path, -1, "frame" );
gtk_widget_path_iter_add_class(path, -1, "top" );
return makeContext(path, mpNotebookStyle);
}
case GtkControlPart::NotebookHeaderTabs:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
gtk_widget_path_iter_set_object_name(path, -1, "tabs" );
gtk_widget_path_iter_add_class(path, -1, "top" );
return makeContext(path, mpNotebookHeaderStyle);
}
case GtkControlPart::NotebookHeaderTabsTab:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
gtk_widget_path_iter_set_object_name(path, -1, "tab" );
gtk_widget_path_iter_add_class(path, -1, "top" );
return makeContext(path, mpNotebookHeaderTabsStyle);
}
case GtkControlPart::NotebookHeaderTabsTabLabel:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "label" );
return makeContext(path, mpNotebookHeaderTabsTabStyle);
}
case GtkControlPart::NotebookHeaderTabsTabActiveLabel:
case GtkControlPart::NotebookHeaderTabsTabHoverLabel:
return mpNotebookHeaderTabsTabLabelStyle;
case GtkControlPart::FrameBorder:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_FRAME);
gtk_widget_path_iter_set_object_name(path, -1, "frame" );
gtk_widget_path_iter_add_class(path, -1, "frame" );
return makeContext(path, nullptr);
}
case GtkControlPart::MenuBar:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
gtk_widget_path_append_type(path, GTK_TYPE_MENU_BAR);
gtk_widget_path_iter_set_object_name(path, -1, "menubar" );
gtk_widget_path_iter_add_class(path, -1, "background" );
return makeContext(path, mpWindowStyle);
}
case GtkControlPart::MenuBarItem:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarStyle));
gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "menuitem" );
return makeContext(path, mpMenuBarStyle);
}
case GtkControlPart::MenuWindow:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarItemStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "window" );
gtk_widget_path_iter_add_class(path, -1, "background" );
gtk_widget_path_iter_add_class(path, -1, "popup" );
return makeContext(path, mpMenuBarItemStyle);
}
case GtkControlPart::Menu:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuWindowStyle));
gtk_widget_path_append_type(path, GTK_TYPE_MENU);
gtk_widget_path_iter_set_object_name(path, -1, "menu" );
return makeContext(path, mpMenuWindowStyle);
}
case GtkControlPart::MenuItem:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "menuitem" );
return makeContext(path, mpMenuStyle);
}
case GtkControlPart::MenuItemLabel:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
gtk_widget_path_append_type(path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name(path, -1, "label" );
return makeContext(path, mpMenuItemStyle);
}
case GtkControlPart::MenuItemArrow:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "arrow" );
return makeContext(path, mpMenuItemStyle);
}
case GtkControlPart::CheckMenuItem:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "menuitem" );
return makeContext(path, mpMenuStyle);
}
case GtkControlPart::CheckMenuItemCheck:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckMenuItemStyle));
gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "check" );
return makeContext(path, mpCheckMenuItemStyle);
}
case GtkControlPart::RadioMenuItem:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "menuitem" );
return makeContext(path, mpMenuStyle);
}
case GtkControlPart::RadioMenuItemRadio:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioMenuItemStyle));
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "radio" );
return makeContext(path, mpRadioMenuItemStyle);
}
case GtkControlPart::SeparatorMenuItem:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "menuitem" );
return makeContext(path, mpMenuStyle);
}
case GtkControlPart::SeparatorMenuItemSeparator:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSeparatorMenuItemStyle));
gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
gtk_widget_path_iter_set_object_name(path, -1, "separator" );
return makeContext(path, mpSeparatorMenuItemStyle);
}
}
return nullptr;
}
#ifndef GTK_STYLE_CLASS_POPUP
constexpr OUStringLiteral GTK_STYLE_CLASS_POPUP = u"popup" ;
#endif
#ifndef GTK_STYLE_CLASS_LABEL
constexpr OUStringLiteral GTK_STYLE_CLASS_LABEL = u"label" ;
#endif
void GtkSalGraphics::PaintCheckOrRadio(cairo_t *cr, GtkStyleContext *context,
const tools::Rectangle& rControlRectangle, bool bIsCheck, bool bInMenu)
{
gint indicator_size;
gtk_style_context_get_style(context, "indicator-size" , &indicator_size, nullptr);
gint x = (rControlRectangle.GetWidth() - indicator_size) / 2;
gint y = (rControlRectangle.GetHeight() - indicator_size) / 2;
if (!bInMenu)
gtk_render_background(context, cr, x, y, indicator_size, indicator_size);
if (bIsCheck)
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=97 H=93 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
¤
*© Formatika GbR, Deutschland