Files
libreoffice/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
Caolán McNamara 2fdbe655bb gtk3: scrollbar damage area one pixel too narrow/short
under default Ambience theme Ubuntu 16.04

tools rectangle strikes again, rejig to be left/top +
width/height rather than left/top + right/bottom

Change-Id: Id5274f068863cd5219a89142b392c9ca53a1694d
Reviewed-on: https://gerrit.libreoffice.org/30850
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
2016-11-14 16:28:00 +00:00

3103 lines
133 KiB
C++

/* -*- 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 <basegfx/range/b2ibox.hxx>
#include <unx/gtk/gtkframe.hxx>
#include <unx/gtk/gtkdata.hxx>
#include <unx/gtk/gtkinst.hxx>
#include <unx/gtk/gtkgdi.hxx>
#include <vcl/decoview.hxx>
#include <vcl/settings.hxx>
#include "unx/fontmanager.hxx"
#include "cairo_gtk3_cairo.hxx"
#if defined(GDK_WINDOWING_WAYLAND)
# include <gdk/gdkwayland.h>
#endif
#include <boost/optional.hpp>
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::mpToolbarSeperatorStyle = 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;
bool GtkSalGraphics::style_loaded = false;
/************************************************************************
* State conversion
************************************************************************/
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 = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_ACTIVE);
}
if ( nVCLState & ControlState::ROLLOVER )
{
nGTKState = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_PRELIGHT);
}
if ( nVCLState & ControlState::SELECTED )
nGTKState = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_SELECTED);
if ( nVCLState & ControlState::FOCUSED )
nGTKState = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_FOCUSED);
if (AllSettings::GetLayoutRTL())
{
nGTKState = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_DIR_RTL);
}
else
{
nGTKState = (GtkStateFlags) (nGTKState | GTK_STATE_FLAG_DIR_LTR);
}
return nGTKState;
}
enum class RenderType {
BackgroundAndFrame = 1,
Check,
Background,
MenuSeparator,
ToolbarSeparator,
Separator,
Arrow,
Radio,
Scrollbar,
Spinbutton,
Combobox,
Expander,
Icon,
Progress,
TabItem,
Focus
};
static void NWCalcArrowRect( const Rectangle& rButton, 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
) );
}
Rectangle GtkSalGraphics::NWGetSpinButtonRect( ControlPart nPart, 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;
gtk_style_context_get_padding(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &padding);
gtk_style_context_get_border(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &border);
gint buttonWidth = icon_size + padding.left + padding.right +
border.left + border.right;
gint buttonHeight = icon_size + padding.top + padding.bottom +
border.top + border.bottom;
Rectangle buttonRect;
buttonRect.SetSize(Size(buttonWidth, buttonHeight));
buttonRect.setY(aAreaRect.Top());
buttonRect.Bottom() = buttonRect.Top() + aAreaRect.GetHeight();
Rectangle partRect(buttonRect);
if ( nPart == ControlPart::ButtonUp )
{
if (AllSettings::GetLayoutRTL())
partRect.setX(aAreaRect.Left());
else
partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()));
}
else if( nPart == ControlPart::ButtonDown )
{
if (AllSettings::GetLayoutRTL())
partRect.setX(aAreaRect.Left() + buttonRect.GetWidth());
else
partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth()));
}
else
{
if (AllSettings::GetLayoutRTL())
{
partRect.Right() = aAreaRect.Left() + aAreaRect.GetWidth();
partRect.Left() = aAreaRect.Left() + (2 * buttonRect.GetWidth()) - 1;
}
else
{
partRect.Right() = (aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth())) - 1;
partRect.Left() = aAreaRect.Left();
}
partRect.Top() = aAreaRect.Top();
partRect.Bottom() = aAreaRect.Bottom();
}
return partRect;
}
Rectangle GtkSalGraphics::NWGetScrollButtonRect( ControlPart nPart, Rectangle aAreaRect )
{
GtkStyleContext* pScrollbarStyle = nullptr;
if ((nPart == ControlPart::ButtonLeft) || (nPart == ControlPart::ButtonRight))
pScrollbarStyle = mpHScrollbarStyle;
else // (nPart == ControlPart::ButtonUp) || (nPart == ControlPart::ButtonDown)
pScrollbarStyle = mpVScrollbarStyle;
gint slider_width;
gint stepper_size;
gint stepper_spacing;
gint trough_border;
// Grab some button style attributes
gtk_style_context_get_style( pScrollbarStyle,
"slider-width", &slider_width,
"stepper-size", &stepper_size,
"trough-border", &trough_border,
"stepper-spacing", &stepper_spacing, nullptr );
gboolean has_forward;
gboolean has_forward2;
gboolean has_backward;
gboolean has_backward2;
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 buttonWidth;
gint buttonHeight;
Rectangle buttonRect;
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;
if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonDown ) )
{
buttonWidth = slider_width + 2 * trough_border;
buttonHeight = stepper_size + trough_border + stepper_spacing;
}
else
{
buttonWidth = stepper_size + trough_border + stepper_spacing;
buttonHeight = slider_width + 2 * trough_border;
}
if ( nPart == ControlPart::ButtonUp )
{
buttonHeight *= nFirst;
buttonHeight -= 1;
buttonRect.setX( aAreaRect.Left() );
buttonRect.setY( aAreaRect.Top() );
}
else if ( nPart == ControlPart::ButtonLeft )
{
buttonWidth *= nFirst;
buttonWidth -= 1;
buttonRect.setX( aAreaRect.Left() );
buttonRect.setY( aAreaRect.Top() );
}
else if ( nPart == ControlPart::ButtonDown )
{
buttonHeight *= nSecond;
buttonRect.setX( aAreaRect.Left() );
buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
}
else if ( nPart == ControlPart::ButtonRight )
{
buttonWidth *= nSecond;
buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
buttonRect.setY( aAreaRect.Top() );
}
buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
return buttonRect;
}
static GtkWidget* gCacheWindow;
static GtkWidget* gDumbContainer;
static GtkWidget* gSpinBox;
static GtkWidget* gEntryBox;
static GtkWidget* gComboBox;
static GtkWidget* gListBox;
static GtkWidget* gMenuBarWidget;
static GtkWidget* gMenuItemMenuBarWidget;
static GtkWidget* gCheckMenuItemWidget;
static GtkWidget* gTreeViewWidget;
namespace
{
void parent_styles_context_set_state(GtkStyleContext* context, GtkStateFlags flags)
{
while ((context = gtk_style_context_get_parent(context)))
{
gtk_style_context_set_state(context, flags);
}
}
void style_context_set_state(GtkStyleContext* context, GtkStateFlags flags)
{
gtk_style_context_set_state(context, flags);
parent_styles_context_set_state(context, flags);
}
Rectangle render_common(GtkStyleContext *pContext, cairo_t *cr, const Rectangle &rIn, GtkStateFlags flags)
{
if (!pContext)
return rIn;
gtk_style_context_set_state(pContext, flags);
Rectangle aRect(rIn);
GtkBorder margin;
gtk_style_context_get_margin(pContext, gtk_style_context_get_state(pContext), &margin);
aRect.Left() += margin.left;
aRect.Top() += margin.top;
aRect.Right() -= margin.right;
aRect.Bottom() -= 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;
gtk_style_context_get_border(pContext, gtk_style_context_get_state(pContext), &border);
gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &padding);
aRect.Left() += border.left + padding.left;
aRect.Top() += border.top + padding.top;
aRect.Right() -= border.right + padding.right;
aRect.Bottom() -= border.bottom + padding.bottom;
return aRect;
}
}
void GtkSalGraphics::PaintScrollbar(GtkStyleContext *context,
cairo_t *cr,
const Rectangle& rControlRectangle,
ControlType nType,
ControlPart nPart,
const ImplControlValue& rValue )
{
(void)nType;
OSL_ASSERT( rValue.getType() == ControlType::Scrollbar );
const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(rValue);
Rectangle scrollbarRect;
GtkStateFlags stateFlags;
GtkOrientation scrollbarOrientation;
Rectangle thumbRect = rScrollbarVal.maThumbRect;
Rectangle button11BoundRect = rScrollbarVal.maButton1Rect; // backward
Rectangle button22BoundRect = rScrollbarVal.maButton2Rect; // forward
Rectangle button12BoundRect = rScrollbarVal.maButton1Rect; // secondary forward
Rectangle button21BoundRect = rScrollbarVal.maButton2Rect; // secondary backward
gdouble arrow1Angle; // backward
gdouble arrow2Angle; // forward
Rectangle arrowRect;
gint slider_width = 0;
gint stepper_size = 0;
gint stepper_spacing = 0;
gint trough_border = 0;
gint min_slider_length = 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;
scrollbarRect.SetSize( Size( scrollbarRect.GetWidth() + 1,
scrollbarRect.GetHeight() + 1 ) );
if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
return;
// Grab some button style attributes
gtk_style_context_get_style( context,
"slider_width", &slider_width,
"stepper_size", &stepper_size,
"trough_border", &trough_border,
"stepper_spacing", &stepper_spacing,
"min_slider_length", &min_slider_length, 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 );
gint magic = trough_border ? 1 : 0;
gint slider_side = slider_width + (trough_border * 2);
if ( nPart == ControlPart::DrawBackgroundHorz )
{
scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
arrow1Angle = G_PI * 3 / 2;
arrow2Angle = G_PI / 2;
if ( has_backward )
{
button12BoundRect.Move( stepper_size - trough_border,
(scrollbarRect.GetHeight() - slider_width) / 2 );
}
button11BoundRect.Move( trough_border, (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+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
}
else
{
button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
}
button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
thumbRect.Bottom() = thumbRect.Top() + slider_width - 1;
// Make sure the thumb is at least the default width (so we don't get tiny thumbs),
// but if the VCL gives us a size smaller than the theme's default thumb size,
// honor the VCL size
thumbRect.Right() += magic;
// Center vertically in the track
thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
}
else
{
scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
arrow1Angle = 0;
arrow2Angle = G_PI;
if ( has_backward )
{
button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
stepper_size + trough_border );
}
button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
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+(trough_border+1)/2 );
button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
}
else
{
button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
}
button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
thumbRect.Right() = thumbRect.Left() + slider_width - 1;
thumbRect.Bottom() += magic;
// Center horizontally in the track
thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
}
bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
// ----------------- 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() );
// ----------------- TROUGH
GtkStyleContext* pScrollbarTroughStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
gtk_render_background(pScrollbarTroughStyle, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
gtk_render_frame(pScrollbarTroughStyle, cr, 0, 0,
scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
// ----------------- THUMB
if ( has_slider )
{
stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnThumbState);
if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
stateFlags = (GtkStateFlags) (stateFlags | GTK_STATE_PRELIGHT);
GtkStyleContext* pScrollbarSliderStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
mpVScrollbarSliderStyle : mpHScrollbarSliderStyle;
gtk_style_context_set_state(pScrollbarSliderStyle, stateFlags);
GtkBorder margin;
gtk_style_context_get_margin(pScrollbarSliderStyle, stateFlags, &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);
}
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_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()) );
}
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()) );
}
}
void GtkSalGraphics::PaintOneSpinButton( GtkStyleContext *context,
cairo_t *cr,
ControlType nType,
ControlPart nPart,
Rectangle aAreaRect,
ControlState nState )
{
(void)nType;
GtkBorder padding, border;
GtkStateFlags stateFlags = NWConvertVCLStateToGTKState(nState);
Rectangle buttonRect = NWGetSpinButtonRect( nPart, aAreaRect );
gtk_style_context_set_state(context, stateFlags);
gtk_style_context_get_padding(context, gtk_style_context_get_state(context), &padding);
gtk_style_context_get_border(context, gtk_style_context_get_state(context), &border);
gtk_render_background(context, cr,
buttonRect.Left(), buttonRect.Top(),
buttonRect.GetWidth(), buttonRect.GetHeight() );
gtk_render_frame(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));
GtkIconInfo *info = gtk_icon_theme_lookup_icon(pIconTheme, icon, std::min(iconWidth, iconHeight),
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);
iconHeight = gdk_pixbuf_get_height(pixbuf);
Rectangle arrowRect;
arrowRect.SetSize(Size(iconWidth, iconHeight));
arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 );
gtk_render_icon(context, cr, pixbuf, arrowRect.Left(), arrowRect.Top());
g_object_unref(pixbuf);
}
void GtkSalGraphics::PaintSpinButton(GtkStyleContext *context,
cairo_t *cr,
const Rectangle& rControlRectangle,
ControlType nType,
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_render_background(context, cr,
0, 0,
rControlRectangle.GetWidth(), rControlRectangle.GetHeight() );
gtk_render_frame(context, cr,
0, 0,
rControlRectangle.GetWidth(), rControlRectangle.GetHeight() );
}
cairo_translate(cr, -rControlRectangle.Left(), -rControlRectangle.Top());
PaintOneSpinButton(mpSpinUpStyle, cr, nType, upBtnPart, rControlRectangle, upBtnState );
PaintOneSpinButton(mpSpinDownStyle, cr, nType, downBtnPart, rControlRectangle, downBtnState );
cairo_translate(cr, rControlRectangle.Left(), rControlRectangle.Top());
}
#define FALLBACK_ARROW_SIZE 11 * 0.85
Rectangle GtkSalGraphics::NWGetComboBoxButtonRect( ControlType nType,
ControlPart nPart,
Rectangle aAreaRect )
{
(void)nType;
(void)nPart;
Rectangle aButtonRect;
GtkBorder padding;
gtk_style_context_get_padding( mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &padding);
gint nArrowWidth = FALLBACK_ARROW_SIZE;
if (gtk_check_version(3, 20, 0) == nullptr)
{
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 = Point(aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, aAreaRect.Top());
if (AllSettings::GetLayoutRTL())
aPos.X() = 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.X() += nButtonWidth;
else
aEditPos.X() += adjust_left;
aEditPos.Y() += adjust_top;
aButtonRect.SetPos( aEditPos );
}
return aButtonRect;
}
void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
const Rectangle& rControlRectangle,
ControlType nType,
ControlPart nPart,
const ImplControlValue& /*rValue*/ )
{
Rectangle areaRect;
Rectangle buttonRect;
Rectangle arrowRect;
// Find the overall bounding rect of the buttons's drawing area,
// plus its actual draw rect excluding adornment
areaRect = rControlRectangle;
buttonRect = NWGetComboBoxButtonRect( nType, ControlPart::ButtonDown, areaRect );
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 (gtk_check_version(3, 20, 0) == nullptr)
{
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() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
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);
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);
}
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(mpListboxBoxStyle, cr, aRect, flags);
render_common(mpListboxButtonStyle, 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_iter_set_object_nameFunc set_object_name)
{
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_ENTRY);
set_object_name(pSiblingsPath, -1, "entry");
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
}
static void appendComboButton(GtkWidgetPath* pSiblingsPath, gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
set_object_name(pSiblingsPath, -1, "button");
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
}
static GtkWidgetPath* buildLTRComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboEntry(pSiblingsPath, set_object_name);
appendComboButton(pSiblingsPath, set_object_name);
return pSiblingsPath;
}
static GtkWidgetPath* buildRTLComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboButton(pSiblingsPath, set_object_name);
appendComboEntry(pSiblingsPath, set_object_name);
return pSiblingsPath;
}
GtkStyleContext* GtkSalGraphics::makeContext(GtkWidgetPath *pPath, GtkStyleContext *pParent)
{
GtkStyleContext* context = gtk_style_context_new();
gtk_style_context_set_screen(context, gtk_window_get_screen(GTK_WINDOW(mpWindow)));
gtk_style_context_set_path(context, pPath);
gtk_style_context_set_parent(context, pParent);
gtk_widget_path_unref(pPath);
return context;
}
GtkStyleContext* GtkSalGraphics::createNewContext(GtkControlPart ePart, gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
switch (ePart)
{
case GtkControlPart::ToplevelWindow:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, G_TYPE_NONE);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
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(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
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);
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);
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);
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_new();
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
set_object_name(path, -1, "spinbutton");
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
return makeContext(path, nullptr);
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
set_object_name(path, -1, "progress");
return makeContext(path, mpProgressBarTroughStyle);
}
case GtkControlPart::Notebook:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
set_object_name(path, -1, "notebook");
return makeContext(path, nullptr);
}
case GtkControlPart::NotebookStack:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
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);
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);
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);
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);
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);
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);
set_object_name(path, -1, "menubar");
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
set_object_name(path, -1, "separator");
return makeContext(path, mpSeparatorMenuItemStyle);
}
}
return nullptr;
}
#ifndef GTK_STYLE_CLASS_POPUP
#define GTK_STYLE_CLASS_POPUP "popup"
#endif
#ifndef GTK_STYLE_CLASS_LABEL
#define GTK_STYLE_CLASS_LABEL "label"
#endif
GtkStyleContext* GtkSalGraphics::createOldContext(GtkControlPart ePart)
{
switch (ePart)
{
case GtkControlPart::ToplevelWindow:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_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_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
gtk_widget_path_iter_add_class(path, -1, "button");
gtk_widget_path_iter_add_class(path, -1, "text-button");
return makeContext(path, nullptr);
}
case GtkControlPart::LinkButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_LINK_BUTTON);
gtk_widget_path_iter_add_class(path, -1, "text-button");
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_add_class(path, -1, GTK_STYLE_CLASS_CHECK);
gtk_widget_path_iter_add_class(path, -1, "text-button");
return makeContext(path, nullptr);
}
case GtkControlPart::CheckButtonCheck:
return mpCheckButtonStyle;
case GtkControlPart::RadioButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_RADIO);
gtk_widget_path_iter_add_class(path, -1, "text-button");
return makeContext(path, nullptr);
}
case GtkControlPart::RadioButtonRadio:
return mpRadioButtonStyle;
case GtkControlPart::ComboboxBoxButtonBoxArrow:
case GtkControlPart::ListboxBoxButtonBoxArrow:
{
return (ePart == GtkControlPart::ComboboxBoxButtonBoxArrow)
? mpComboboxButtonStyle : mpListboxButtonStyle;
}
case GtkControlPart::Entry:
case GtkControlPart::ComboboxBoxEntry:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ENTRY);
return makeContext(path, nullptr);
}
case GtkControlPart::Combobox:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX_TEXT);
return makeContext(path, nullptr);
}
case GtkControlPart::Listbox:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX);
return makeContext(path, nullptr);
}
case GtkControlPart::ComboboxBoxButton:
case GtkControlPart::ListboxBoxButton:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ComboboxBoxButton ) ? mpComboboxStyle : mpListboxStyle;
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
gtk_widget_path_append_type(path, GTK_TYPE_TOGGLE_BUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
gtk_widget_path_iter_add_class(path, -1, "the-button-in-the-combobox");
return makeContext(path, pParent);
}
case GtkControlPart::SpinButton:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ENTRY);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SPINBUTTON);
return makeContext(path, nullptr);
}
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_add_class(path, -1, GTK_STYLE_CLASS_SPINBUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
gtk_widget_path_iter_add_class(path, -1, "contents");
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarHorizontalTrough:
case GtkControlPart::ScrollbarVerticalTrough:
{
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_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_TROUGH);
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarHorizontalSlider:
case GtkControlPart::ScrollbarVerticalSlider:
{
GtkStyleContext *pParent =
(ePart == GtkControlPart::ScrollbarVerticalSlider) ? 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_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SLIDER);
return makeContext(path, pParent);
}
case GtkControlPart::ScrollbarHorizontalButton:
case GtkControlPart::ScrollbarVerticalButton:
{
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_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_PROGRESSBAR);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_PROGRESSBAR);
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_add_class(path, -1, GTK_STYLE_CLASS_NOTEBOOK);
gtk_widget_path_iter_add_class(path, -1, "frame");
return makeContext(path, mpWindowStyle);
}
case GtkControlPart::NotebookStack:
return mpNotebookStyle;
case GtkControlPart::NotebookHeader:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HEADER);
gtk_widget_path_iter_add_class(path, -1, "top");
return makeContext(path, gtk_style_context_get_parent(mpNotebookStyle));
}
case GtkControlPart::NotebookHeaderTabs:
return 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_add_class(path, -1, GTK_STYLE_CLASS_HEADER);
gtk_widget_path_iter_add_class(path, -1, "top");
gtk_widget_path_iter_add_region(path, -1, GTK_STYLE_REGION_TAB, static_cast<GtkRegionFlags>(GTK_REGION_EVEN | GTK_REGION_FIRST));
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, GTK_TYPE_LABEL);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
return makeContext(path, mpNotebookHeaderTabsTabStyle);
}
case GtkControlPart::NotebookHeaderTabsTabActiveLabel:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
gtk_widget_path_iter_add_class(path, -1, "active-page");
return makeContext(path, mpNotebookHeaderTabsTabStyle);
}
case GtkControlPart::NotebookHeaderTabsTabHoverLabel:
{
GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
gtk_widget_path_iter_add_class(path, -1, "prelight-page");
return makeContext(path, mpNotebookHeaderTabsTabStyle);
}
case GtkControlPart::FrameBorder:
{
GtkWidgetPath *path = gtk_widget_path_new();
gtk_widget_path_append_type(path, GTK_TYPE_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_add_class(path, -1, GTK_STYLE_CLASS_MENUBAR);
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_add_class(path, -1, GTK_STYLE_CLASS_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, GTK_TYPE_WINDOW);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_POPUP);
gtk_widget_path_iter_add_class(path, -1, "background");
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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_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, GTK_TYPE_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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_CHECK);
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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_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_add_class(path, -1, GTK_STYLE_CLASS_SEPARATOR);
return makeContext(path, mpSeparatorMenuItemStyle);
}
case GtkControlPart::ComboboxBox:
case GtkControlPart::ListboxBox:
case GtkControlPart::ComboboxBoxButtonBox:
case GtkControlPart::ListboxBoxButtonBox:
return nullptr;
default:
break;
}
return mpButtonStyle;
}
GtkStyleContext* GtkSalGraphics::createStyleContext(gtk_widget_path_iter_set_object_nameFunc set_object_name,
GtkControlPart ePart)
{
if (set_object_name)
return createNewContext(ePart, set_object_name);
return createOldContext(ePart);
}
namespace
{
GtkStateFlags CHECKED()
{
#if GTK_CHECK_VERSION(3,14,0)
if (gtk_check_version(3, 14, 0) == nullptr)
return GTK_STATE_FLAG_CHECKED;
#endif
return GTK_STATE_FLAG_ACTIVE;
}
GtkStateFlags ACTIVE_TAB()
{
#if GTK_CHECK_VERSION(3,20,0)
if (gtk_check_version(3, 20, 0) == nullptr)
return GTK_STATE_FLAG_CHECKED;
#endif
return GTK_STATE_FLAG_ACTIVE;
}
}
void GtkSalGraphics::PaintCheckOrRadio(cairo_t *cr, GtkStyleContext *context,
const 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);
gtk_render_frame(context, cr, x, y, indicator_size, indicator_size);
if (bIsCheck)
gtk_render_check(context, cr, x, y, indicator_size, indicator_size);
else
gtk_render_option(context, cr, x, y, indicator_size, indicator_size);
}
void GtkSalGraphics::PaintCheck(cairo_t *cr, GtkStyleContext *context,
const Rectangle& rControlRectangle, bool bInMenu)
{
PaintCheckOrRadio(cr, context, rControlRectangle, true, bInMenu);
}
void GtkSalGraphics::PaintRadio(cairo_t *cr, GtkStyleContext *context,
const Rectangle& rControlRectangle, bool bInMenu)
{
PaintCheckOrRadio(cr, context, rControlRectangle, false, bInMenu);
}
static gfloat getArrowSize(GtkStyleContext* context)
{
gfloat arrow_scaling = 1.0;
gtk_style_context_get_style(context, "arrow-scaling", &arrow_scaling, nullptr);
gfloat arrow_size = 11 * arrow_scaling;
return arrow_size;
}
bool GtkSalGraphics::drawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
ControlState nState, const ImplControlValue& rValue,
const OUString& )
{
RenderType renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::BackgroundAndFrame;
GtkStyleContext *context = nullptr;
const gchar *styleClass = nullptr;
GdkPixbuf *pixbuf = nullptr;
bool bInMenu = false;
GtkStateFlags flags = NWConvertVCLStateToGTKState(nState);
switch(nType)
{
case ControlType::Spinbox:
case ControlType::SpinButtons:
context = mpEntryStyle;
renderType = RenderType::Spinbutton;
break;
case ControlType::Editbox:
context = mpEntryStyle;
break;
case ControlType::MultilineEditbox:
context = mpTextViewStyle;
break;
case ControlType::Combobox:
context = mpComboboxStyle;
renderType = RenderType::Combobox;
break;
case ControlType::Listbox:
if (nPart == ControlPart::Focus)
{
renderType = RenderType::Focus;
context = mpListboxButtonStyle;
}
else
{
renderType = RenderType::Combobox;
context = mpListboxStyle;
}
break;
case ControlType::MenuPopup:
bInMenu = true;
// map selected menu entries in vcl parlance to gtk prelight
if (nPart >= ControlPart::MenuItem && nPart <= ControlPart::SubmenuArrow && (nState & ControlState::SELECTED))
flags = (GtkStateFlags) (flags | GTK_STATE_FLAG_PRELIGHT);
flags = (GtkStateFlags)(flags & ~GTK_STATE_FLAG_ACTIVE);
switch(nPart)
{
case ControlPart::MenuItem:
context = mpMenuItemStyle;
renderType = RenderType::BackgroundAndFrame;
break;
case ControlPart::MenuItemCheckMark:
if (gtk_check_version(3, 20, 0) == nullptr)
context = mpCheckMenuItemCheckStyle;
else
{
context = gtk_widget_get_style_context(gCheckMenuItemWidget);
styleClass = GTK_STYLE_CLASS_CHECK;
}
renderType = RenderType::Check;
nType = ControlType::Checkbox;
if (nState & ControlState::PRESSED)
{
flags = (GtkStateFlags)(flags | CHECKED());
}
break;
case ControlPart::MenuItemRadioMark:
if (gtk_check_version(3, 20, 0) == nullptr)
context = mpRadioMenuItemRadioStyle;
else
{
context = gtk_widget_get_style_context(gCheckMenuItemWidget);
styleClass = GTK_STYLE_CLASS_RADIO;
}
renderType = RenderType::Radio;
nType = ControlType::Radiobutton;
if (nState & ControlState::PRESSED)
{
flags = (GtkStateFlags)(flags | CHECKED());
}
break;
case ControlPart::Separator:
context = mpSeparatorMenuItemSeparatorStyle;
flags = (GtkStateFlags)(GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_INSENSITIVE); //GTK_STATE_FLAG_BACKDROP hack ?
renderType = RenderType::MenuSeparator;
break;
case ControlPart::SubmenuArrow:
if (gtk_check_version(3, 20, 0) == nullptr)
context = mpMenuItemArrowStyle;
else
{
context = gtk_widget_get_style_context(gCheckMenuItemWidget);
styleClass = GTK_STYLE_CLASS_ARROW;
}
renderType = RenderType::Arrow;
break;
case ControlPart::Entire:
context = mpMenuStyle;
renderType = RenderType::Background;
break;
default: break;
}
break;
case ControlType::Toolbar:
switch(nPart)
{
case ControlPart::DrawBackgroundHorz:
case ControlPart::DrawBackgroundVert:
context = mpToolbarStyle;
break;
case ControlPart::Button:
/* For all checkbuttons in the toolbars */
flags = (GtkStateFlags)(flags |
( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL));
context = mpToolButtonStyle;
break;
case ControlPart::SeparatorVert:
context = mpToolbarSeperatorStyle;
renderType = RenderType::ToolbarSeparator;
break;
default:
return false;
}
break;
case ControlType::Radiobutton:
flags = (GtkStateFlags)(flags |
( (rValue.getTristateVal() == ButtonValue::On) ? CHECKED() : GTK_STATE_FLAG_NORMAL));
context = mpRadioButtonRadioStyle;
renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Radio;
break;
case ControlType::Checkbox:
flags = (GtkStateFlags)(flags |
( (rValue.getTristateVal() == ButtonValue::On) ? CHECKED() :
(rValue.getTristateVal() == ButtonValue::Mixed) ? GTK_STATE_FLAG_INCONSISTENT :
GTK_STATE_FLAG_NORMAL));
context = mpCheckButtonCheckStyle;
renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Check;
break;
case ControlType::Pushbutton:
context = mpButtonStyle;
break;
case ControlType::Scrollbar:
switch(nPart)
{
case ControlPart::DrawBackgroundVert:
case ControlPart::DrawBackgroundHorz:
context = (nPart == ControlPart::DrawBackgroundVert)
? mpVScrollbarStyle : mpHScrollbarStyle;
renderType = RenderType::Scrollbar;
break;
default: break;
}
break;
case ControlType::ListNet:
return true;
break;
case ControlType::TabPane:
context = mpNotebookStyle;
break;
case ControlType::TabBody:
context = mpNotebookStackStyle;
break;
case ControlType::TabHeader:
context = mpNotebookHeaderStyle;
break;
case ControlType::TabItem:
context = mpNotebookHeaderTabsTabStyle;
if (nState & ControlState::SELECTED)
flags = (GtkStateFlags) (flags | ACTIVE_TAB());
renderType = RenderType::TabItem;
break;
case ControlType::WindowBackground:
context = gtk_widget_get_style_context(mpWindow);
break;
case ControlType::Frame:
{
DrawFrameStyle nStyle = static_cast<DrawFrameStyle>(rValue.getNumericVal() & 0x0f);
if (nStyle == DrawFrameStyle::In)
context = mpFrameOutStyle;
else
context = mpFrameInStyle;
break;
}
case ControlType::Menubar:
if (nPart == ControlPart::MenuItem)
{
context = mpMenuBarItemStyle;
flags = (!(nState & ControlState::ENABLED)) ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
if (nState & ControlState::SELECTED)
flags = (GtkStateFlags) (flags | GTK_STATE_FLAG_PRELIGHT);
}
else
{
// context = mpMenuBarStyle; why does this not work
context = gtk_widget_get_style_context(mpWindow);
}
break;
case ControlType::Fixedline:
context = nPart == ControlPart::SeparatorHorz ? mpFixedHoriLineStyle : mpFixedVertLineStyle;
renderType = RenderType::Separator;
break;
case ControlType::ListNode:
{
context = mpTreeHeaderButtonStyle;
ButtonValue aButtonValue = rValue.getTristateVal();
if (aButtonValue == ButtonValue::On)
flags = (GtkStateFlags) (flags | CHECKED());
renderType = RenderType::Expander;
break;
}
case ControlType::ListHeader:
context = mpTreeHeaderButtonStyle;
if (nPart == ControlPart::Arrow)
{
const char* icon = (rValue.getNumericVal() & 1) ? "pan-down-symbolic" : "pan-up-symbolic";
GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
pixbuf = gtk_icon_theme_load_icon(pIconTheme, icon,
std::max(rControlRegion.GetWidth(), rControlRegion.GetHeight()),
static_cast<GtkIconLookupFlags>(0), nullptr);
flags = GTK_STATE_FLAG_SELECTED;
renderType = RenderType::Icon;
}
break;
case ControlType::Progress:
context = mpProgressBarProgressStyle;
renderType = RenderType::Progress;
break;
default:
return false;
}
cairo_t *cr = getCairoContext(false);
clipRegion(cr);
cairo_translate(cr, rControlRegion.Left(), rControlRegion.Top());
long nX = 0;
long nY = 0;
long nWidth = rControlRegion.GetWidth();
long nHeight = rControlRegion.GetHeight();
style_context_set_state(context, flags);
if (styleClass)
{
gtk_style_context_add_class(context, styleClass);
}
switch(renderType)
{
case RenderType::Background:
case RenderType::BackgroundAndFrame:
gtk_render_background(context, cr, nX, nY, nWidth, nHeight);
if (renderType == RenderType::BackgroundAndFrame)
{
gtk_render_frame(context, cr, nX, nY, nWidth, nHeight);
}
break;
case RenderType::Check:
{
PaintCheck(cr, context, rControlRegion, bInMenu);
break;
}
case RenderType::Radio:
{
PaintRadio(cr, context, rControlRegion, bInMenu);
break;
}
case RenderType::MenuSeparator:
gtk_render_line(context, cr,
0, rControlRegion.GetHeight() / 2,
rControlRegion.GetWidth() - 1, rControlRegion.GetHeight() / 2);
break;
case RenderType::ToolbarSeparator:
{
const bool bNewStyle = gtk_check_version(3, 20, 0) == nullptr;
gint nSeparatorWidth = 1;
if (bNewStyle)
{
gtk_style_context_get(context,
gtk_style_context_get_state(context),
"min-width", &nSeparatorWidth, nullptr);
}
gint nHalfSeparatorWidth = nSeparatorWidth / 2;
gint nHalfRegionWidth = rControlRegion.GetWidth() / 2;
nX = nX + nHalfRegionWidth - nHalfSeparatorWidth;
nWidth = nSeparatorWidth;
nY = rControlRegion.GetHeight() * 0.1;
nHeight = rControlRegion.GetHeight() - (2 * nY);
if (bNewStyle)
{
gtk_render_background(context, cr, nX, nY, nSeparatorWidth, nHeight);
gtk_render_frame(context, cr, nX, nY, nSeparatorWidth, nHeight);
}
else
{
gtk_render_line(context, cr, nX, nY, nX, nY + nHeight);
}
break;
}
case RenderType::Separator:
if (nPart == ControlPart::SeparatorHorz)
gtk_render_line(context, cr, 0, nHeight / 2, nWidth - 1, nHeight / 2);
else
gtk_render_line(context, cr, nWidth / 2, 0, nWidth / 2, nHeight - 1);
break;
case RenderType::Arrow:
gtk_render_arrow(context, cr,
G_PI / 2, 0, 0,
MIN(rControlRegion.GetWidth(), 1 + rControlRegion.GetHeight()));
break;
case RenderType::Expander:
gtk_render_expander(context, cr, -2, -2, nWidth+4, nHeight+4);
break;
case RenderType::Scrollbar:
PaintScrollbar(context, cr, rControlRegion, nType, nPart, rValue);
break;
case RenderType::Spinbutton:
PaintSpinButton(context, cr, rControlRegion, nType, nPart, rValue);
break;
case RenderType::Combobox:
PaintCombobox(flags, cr, rControlRegion, nType, nPart, rValue);
break;
case RenderType::Icon:
gtk_render_icon(context, cr, pixbuf, nX, nY);
g_object_unref(pixbuf);
break;
case RenderType::Focus:
{
if (nType != ControlType::Checkbox)
{
GtkBorder border;
gtk_style_context_get_border(context, flags, &border);
nX += border.left;
nY += border.top;
nWidth -= border.left + border.right;
nHeight -= border.top + border.bottom;
}
gtk_render_focus(context, cr, nX, nY, nWidth, nHeight);
break;
}
case RenderType::Progress:
{
gtk_render_background(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
gtk_render_frame(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
long nProgressWidth = rValue.getNumericVal();
if (nProgressWidth)
{
GtkBorder padding;
gtk_style_context_get_padding(context, gtk_style_context_get_state(context), &padding);
nX += padding.left;
nY += padding.top;
nHeight -= (padding.top + padding.bottom);
nProgressWidth -= (padding.left + padding.right);
gtk_render_background(context, cr, nX, nY, nProgressWidth, nHeight);
gtk_render_frame(context, cr, nX, nY, nProgressWidth, nHeight);
}
break;
}
case RenderType::TabItem:
{
if (gtk_check_version(3, 20, 0) != nullptr)
{
gint initial_gap(0);
gtk_style_context_get_style(mpNotebookStyle,
"initial-gap", &initial_gap,
nullptr);
nX += initial_gap/2;
nWidth -= initial_gap;
}
Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
render_common(mpNotebookHeaderTabsTabStyle, cr, aRect, flags);
break;
}
default:
break;
}
if (styleClass)
{
gtk_style_context_remove_class(context, styleClass);
}
cairo_destroy(cr); // unref
if (!rControlRegion.IsEmpty())
mpFrame->damaged(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight());
return true;
}
Rectangle GetWidgetSize(const Rectangle& rControlRegion, GtkWidget* widget)
{
GtkRequisition aReq;
gtk_widget_get_preferred_size(widget, nullptr, &aReq);
long nHeight = (rControlRegion.GetHeight() > aReq.height) ? rControlRegion.GetHeight() : aReq.height;
return Rectangle(rControlRegion.TopLeft(), Size(rControlRegion.GetWidth(), nHeight));
}
Rectangle AdjustRectForTextBordersPadding(GtkStyleContext* pStyle, long nContentWidth, long nContentHeight, const Rectangle& rControlRegion)
{
GtkBorder border;
gtk_style_context_get_border(pStyle, gtk_style_context_get_state(pStyle), &border);
GtkBorder padding;
gtk_style_context_get_padding(pStyle, gtk_style_context_get_state(pStyle), &padding);
gint nWidgetHeight = nContentHeight + padding.top + padding.bottom + border.top + border.bottom;
nWidgetHeight = std::max(std::max<gint>(nWidgetHeight, rControlRegion.GetHeight()), 34);
gint nWidgetWidth = nContentWidth + padding.left + padding.right + border.left + border.right;
nWidgetWidth = std::max<gint>(nWidgetWidth, rControlRegion.GetWidth());
Rectangle aEditRect(rControlRegion.TopLeft(), Size(nWidgetWidth, nWidgetHeight));
return aEditRect;
}
bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState,
const ImplControlValue& rValue, const OUString&,
Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion )
{
/* TODO: all this functions needs improvements */
Rectangle aEditRect = rControlRegion;
gint indicator_size, indicator_spacing, point;
if(((nType == ControlType::Checkbox) || (nType == ControlType::Radiobutton)) &&
nPart == ControlPart::Entire)
{
rNativeBoundingRegion = rControlRegion;
GtkStyleContext *pButtonStyle = (nType == ControlType::Checkbox) ? mpCheckButtonCheckStyle : mpRadioButtonRadioStyle;
gtk_style_context_get_style( pButtonStyle,
"indicator-size", &indicator_size,
"indicator-spacing", &indicator_spacing,
nullptr );
GtkBorder border;
gtk_style_context_get_border(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &border);
GtkBorder padding;
gtk_style_context_get_padding(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &padding);
indicator_size += 2*indicator_spacing + border.left + padding.left + border.right + padding.right;
Rectangle aIndicatorRect( Point( 0,
(rControlRegion.GetHeight()-indicator_size)/2),
Size( indicator_size, indicator_size ) );
rNativeContentRegion = aIndicatorRect;
return true;
}
else if( nType == ControlType::MenuPopup)
{
if (((nPart == ControlPart::MenuItemCheckMark) ||
(nPart == ControlPart::MenuItemRadioMark) ))
{
indicator_size = 0;
GtkStyleContext *pMenuItemStyle = (nPart == ControlPart::MenuItemCheckMark ) ? mpCheckMenuItemCheckStyle
: mpRadioMenuItemRadioStyle;
gtk_style_context_get_style( pMenuItemStyle,
"indicator-size", &indicator_size,
nullptr );
point = MAX(0, rControlRegion.GetHeight() - indicator_size);
aEditRect = Rectangle( Point( 0, point / 2),
Size( indicator_size, indicator_size ) );
}
else if (nPart == ControlPart::Separator)
{
gint separator_height, separator_width, wide_separators;
gtk_style_context_get_style (mpSeparatorMenuItemSeparatorStyle,
"wide-separators", &wide_separators,
"separator-width", &separator_width,
"separator-height", &separator_height,
nullptr);
aEditRect = Rectangle( aEditRect.TopLeft(),
Size( aEditRect.GetWidth(), wide_separators ? separator_height : 1 ) );
}
else if (nPart == ControlPart::SubmenuArrow)
{
gfloat arrow_size = getArrowSize(mpMenuItemArrowStyle);
aEditRect = Rectangle( aEditRect.TopLeft(),
Size( arrow_size, arrow_size ) );
}
}
else if ( (nType==ControlType::Scrollbar) &&
((nPart==ControlPart::ButtonLeft) || (nPart==ControlPart::ButtonRight) ||
(nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ) )
{
rNativeBoundingRegion = NWGetScrollButtonRect( nPart, rControlRegion );
rNativeContentRegion = rNativeBoundingRegion;
if (!rNativeContentRegion.GetWidth())
rNativeContentRegion.Right() = rNativeContentRegion.Left() + 1;
if (!rNativeContentRegion.GetHeight())
rNativeContentRegion.Bottom() = rNativeContentRegion.Top() + 1;
return true;
}
else if ( (nType==ControlType::Spinbox) &&
((nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ||
(nPart==ControlPart::SubEdit)) )
{
Rectangle aControlRegion(GetWidgetSize(rControlRegion, gSpinBox));
aEditRect = NWGetSpinButtonRect(nPart, aControlRegion);
}
else if ( (nType==ControlType::Combobox) &&
((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
{
aEditRect = NWGetComboBoxButtonRect( nType, nPart, rControlRegion );
}
else if ( (nType==ControlType::Listbox) &&
((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
{
aEditRect = NWGetComboBoxButtonRect( nType, nPart, rControlRegion );
}
else if (nType == ControlType::Editbox && nPart == ControlPart::Entire)
{
aEditRect = GetWidgetSize(rControlRegion, gEntryBox);
}
else if (nType == ControlType::Listbox && nPart == ControlPart::Entire)
{
aEditRect = GetWidgetSize(rControlRegion, gListBox);
}
else if (nType == ControlType::Combobox && nPart == ControlPart::Entire)
{
aEditRect = GetWidgetSize(rControlRegion, gComboBox);
}
else if (nType == ControlType::Spinbox && nPart == ControlPart::Entire)
{
aEditRect = GetWidgetSize(rControlRegion, gSpinBox);
}
else if (nType == ControlType::TabItem && nPart == ControlPart::Entire)
{
const TabitemValue& rTabitemValue = static_cast<const TabitemValue&>(rValue);
const Rectangle& rTabitemRect = rTabitemValue.getContentRect();
aEditRect = AdjustRectForTextBordersPadding(mpNotebookHeaderTabsTabStyle, rTabitemRect.GetWidth(),
rTabitemRect.GetHeight(), rControlRegion);
}
else if (nType == ControlType::Frame && nPart == ControlPart::Border)
{
aEditRect = rControlRegion;
DrawFrameFlags nStyle = static_cast<DrawFrameFlags>(rValue.getNumericVal() & 0xfff0);
if (nStyle & DrawFrameFlags::NoDraw)
{
GtkBorder padding;
gtk_style_context_get_padding(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &padding);
GtkBorder border;
gtk_style_context_get_border(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &border);
int x1 = aEditRect.Left();
int y1 = aEditRect.Top();
int x2 = aEditRect.Right();
int y2 = aEditRect.Bottom();
rNativeBoundingRegion = aEditRect;
rNativeContentRegion = Rectangle(x1 + (padding.left + border.left),
y1 + (padding.top + border.top),
x2 - (padding.right + border.right),
y2 - (padding.bottom + border.bottom));
return true;
}
else
rNativeContentRegion = rControlRegion;
}
else
{
return false;
}
rNativeBoundingRegion = aEditRect;
rNativeContentRegion = rNativeBoundingRegion;
return true;
}
/************************************************************************
* helper for GtkSalFrame
************************************************************************/
static inline ::Color getColor( const GdkRGBA& rCol )
{
return ::Color( (int)(rCol.red * 0xFFFF) >> 8, (int)(rCol.green * 0xFFFF) >> 8, (int)(rCol.blue * 0xFFFF) >> 8 );
}
static vcl::Font getFont(GtkStyleContext* pStyle, const css::lang::Locale& rLocale)
{
const PangoFontDescription* font = gtk_style_context_get_font(pStyle, gtk_style_context_get_state(pStyle));
OString aFamily = pango_font_description_get_family( font );
int nPangoHeight = pango_font_description_get_size( font );
PangoStyle eStyle = pango_font_description_get_style( font );
PangoWeight eWeight = pango_font_description_get_weight( font );
PangoStretch eStretch = pango_font_description_get_stretch( font );
psp::FastPrintFontInfo aInfo;
// set family name
aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
// set italic
switch( eStyle )
{
case PANGO_STYLE_NORMAL: aInfo.m_eItalic = ITALIC_NONE;break;
case PANGO_STYLE_ITALIC: aInfo.m_eItalic = ITALIC_NORMAL;break;
case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = ITALIC_OBLIQUE;break;
}
// set weight
if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
aInfo.m_eWeight = WEIGHT_ULTRALIGHT;
else if( eWeight <= PANGO_WEIGHT_LIGHT )
aInfo.m_eWeight = WEIGHT_LIGHT;
else if( eWeight <= PANGO_WEIGHT_NORMAL )
aInfo.m_eWeight = WEIGHT_NORMAL;
else if( eWeight <= PANGO_WEIGHT_BOLD )
aInfo.m_eWeight = WEIGHT_BOLD;
else
aInfo.m_eWeight = WEIGHT_ULTRABOLD;
// set width
switch( eStretch )
{
case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = WIDTH_ULTRA_CONDENSED;break;
case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = WIDTH_EXTRA_CONDENSED;break;
case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = WIDTH_CONDENSED;break;
case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = WIDTH_SEMI_CONDENSED;break;
case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = WIDTH_NORMAL;break;
case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = WIDTH_SEMI_EXPANDED;break;
case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = WIDTH_EXPANDED;break;
case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = WIDTH_EXTRA_EXPANDED;break;
case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = WIDTH_ULTRA_EXPANDED;break;
}
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
#endif
// match font to e.g. resolve "Sans"
psp::PrintFontManager::get().matchFont(aInfo, rLocale);
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
aInfo.m_nID != 0 ? "succeeded" : "failed",
OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
#endif
int nPointHeight = 0;
nPointHeight = nPangoHeight/PANGO_SCALE;
vcl::Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
if( aInfo.m_eWeight != WEIGHT_DONTKNOW )
aFont.SetWeight( aInfo.m_eWeight );
if( aInfo.m_eWidth != WIDTH_DONTKNOW )
aFont.SetWidthType( aInfo.m_eWidth );
if( aInfo.m_eItalic != ITALIC_DONTKNOW )
aFont.SetItalic( aInfo.m_eItalic );
if( aInfo.m_ePitch != PITCH_DONTKNOW )
aFont.SetPitch( aInfo.m_ePitch );
return aFont;
}
void GtkSalGraphics::updateSettings( AllSettings& rSettings )
{
GtkStyleContext* pStyle = gtk_widget_get_style_context( mpWindow );
GtkSettings* pSettings = gtk_widget_get_settings( mpWindow );
StyleSettings aStyleSet = rSettings.GetStyleSettings();
GdkRGBA color;
// text colors
GdkRGBA text_color;
style_context_set_state(pStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
::Color aTextColor = getColor( text_color );
aStyleSet.SetDialogTextColor( aTextColor );
aStyleSet.SetButtonTextColor( aTextColor );
aStyleSet.SetRadioCheckTextColor( aTextColor );
aStyleSet.SetGroupTextColor( aTextColor );
aStyleSet.SetLabelTextColor( aTextColor );
aStyleSet.SetWindowTextColor( aTextColor );
aStyleSet.SetFieldTextColor( aTextColor );
// background colors
GdkRGBA background_color;
gtk_style_context_get_background_color(pStyle, gtk_style_context_get_state(pStyle), &background_color);
::Color aBackColor = getColor( background_color );
aStyleSet.Set3DColors( aBackColor );
aStyleSet.SetFaceColor( aBackColor );
aStyleSet.SetDialogColor( aBackColor );
aStyleSet.SetWorkspaceColor( aBackColor );
aStyleSet.SetCheckedColorSpecialCase( );
// UI font
vcl::Font aFont(getFont(pStyle, rSettings.GetUILanguageTag().getLocale()));
aStyleSet.SetAppFont( aFont );
aStyleSet.SetHelpFont( aFont );
aStyleSet.SetMenuFont( aFont );
aStyleSet.SetToolFont( aFont );
aStyleSet.SetLabelFont( aFont );
aStyleSet.SetRadioCheckFont( aFont );
aStyleSet.SetPushButtonFont( aFont );
aStyleSet.SetFieldFont( aFont );
aStyleSet.SetIconFont( aFont );
aStyleSet.SetGroupFont( aFont );
aFont.SetWeight( WEIGHT_BOLD );
aStyleSet.SetTitleFont( aFont );
aStyleSet.SetFloatTitleFont( aFont );
// mouse over text colors
style_context_set_state(pStyle, GTK_STATE_FLAG_PRELIGHT);
gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
aTextColor = getColor( text_color );
aStyleSet.SetButtonRolloverTextColor( aTextColor );
aStyleSet.SetFieldRolloverTextColor( aTextColor );
// tooltip colors
{
GtkStyleContext *pCStyle = gtk_style_context_new();
gtk_style_context_set_screen( pCStyle, gtk_window_get_screen( GTK_WINDOW( mpWindow ) ) );
GtkWidgetPath *pCPath = gtk_widget_path_new();
guint pos = gtk_widget_path_append_type(pCPath, GTK_TYPE_WINDOW);
gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_TOOLTIP);
pos = gtk_widget_path_append_type (pCPath, GTK_TYPE_LABEL);
gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_LABEL);
pCStyle = gtk_style_context_new();
gtk_style_context_set_path(pCStyle, pCPath);
gtk_widget_path_free(pCPath);
GdkRGBA tooltip_bg_color, tooltip_fg_color;
style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_fg_color);
gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_bg_color);
g_object_unref( pCStyle );
aStyleSet.SetHelpColor( getColor( tooltip_bg_color ));
aStyleSet.SetHelpTextColor( getColor( tooltip_fg_color ));
}
{
// construct style context for text view
GtkStyleContext *pCStyle = gtk_style_context_new();
gtk_style_context_set_screen( pCStyle, gtk_window_get_screen( GTK_WINDOW( mpWindow ) ) );
GtkWidgetPath *pCPath = gtk_widget_path_new();
gtk_widget_path_append_type( pCPath, GTK_TYPE_TEXT_VIEW );
gtk_widget_path_iter_add_class( pCPath, -1, GTK_STYLE_CLASS_VIEW );
gtk_style_context_set_path( pCStyle, pCPath );
gtk_widget_path_free( pCPath );
// highlighting colors
style_context_set_state(pCStyle, GTK_STATE_FLAG_SELECTED);
gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
::Color aHighlightColor = getColor( text_color );
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
::Color aHighlightTextColor = getColor( text_color );
aStyleSet.SetHighlightColor( aHighlightColor );
aStyleSet.SetHighlightTextColor( aHighlightTextColor );
// field background color
GdkRGBA field_background_color;
style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &field_background_color);
::Color aBackFieldColor = getColor( field_background_color );
aStyleSet.SetFieldColor( aBackFieldColor );
// This baby is the default page/paper color
aStyleSet.SetWindowColor( aBackFieldColor );
// Dark shadow color
style_context_set_state(pCStyle, GTK_STATE_FLAG_INSENSITIVE);
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &color);
::Color aDarkShadowColor = getColor( color );
aStyleSet.SetDarkShadowColor( aDarkShadowColor );
g_object_unref( pCStyle );
// Tab colors
aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
aStyleSet.SetInactiveTabColor( aBackColor );
}
// menu disabled entries handling
aStyleSet.SetSkipDisabledInMenus( true );
aStyleSet.SetPreferredContextMenuShortcuts( false );
// menu colors
style_context_set_state(mpMenuStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_background_color( mpMenuStyle, gtk_style_context_get_state(mpMenuStyle), &background_color );
aBackColor = getColor( background_color );
aStyleSet.SetMenuColor( aBackColor );
// menu bar
style_context_set_state(mpMenuBarStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_background_color( mpMenuBarStyle, gtk_style_context_get_state(mpMenuBarStyle), &background_color );
aBackColor = getColor( background_color );
aStyleSet.SetMenuBarColor( aBackColor );
aStyleSet.SetMenuBarRolloverColor( aBackColor );
style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
aStyleSet.SetMenuBarTextColor( aTextColor );
aStyleSet.SetMenuBarRolloverTextColor( aTextColor );
style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_PRELIGHT);
gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
aStyleSet.SetMenuBarHighlightTextColor( aTextColor );
// menu items
style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_color(mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color);
aTextColor = getColor(color);
aStyleSet.SetMenuTextColor(aTextColor);
style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_PRELIGHT);
gtk_style_context_get_background_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &background_color );
::Color aHighlightColor = getColor( background_color );
aStyleSet.SetMenuHighlightColor( aHighlightColor );
gtk_style_context_get_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color );
::Color aHighlightTextColor = getColor( color );
aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
#if GTK_CHECK_VERSION(3, 12, 0)
// hyperlink colors
style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_LINK);
gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
aStyleSet.SetLinkColor(getColor(text_color));
style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_VISITED);
gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
aStyleSet.SetVisitedLinkColor(getColor(text_color));
#endif
{
GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabLabelStyle;
style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
aTextColor = getColor( text_color );
aStyleSet.SetTabTextColor(aTextColor);
aStyleSet.SetTabFont(getFont(mpNotebookHeaderTabsTabLabelStyle, rSettings.GetUILanguageTag().getLocale()));
}
// mouse over text colors
{
GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabHoverLabelStyle;
style_context_set_state(pCStyle, GTK_STATE_FLAG_PRELIGHT);
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
aTextColor = getColor( text_color );
aStyleSet.SetTabRolloverTextColor(aTextColor);
}
{
GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabActiveLabelStyle;
style_context_set_state(pCStyle, ACTIVE_TAB());
gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
aTextColor = getColor( text_color );
aStyleSet.SetTabHighlightTextColor(aTextColor);
}
// get cursor blink time
gboolean blink = false;
g_object_get( pSettings, "gtk-cursor-blink", &blink, nullptr );
if( blink )
{
gint blink_time = static_cast<gint>(STYLE_CURSOR_NOBLINKTIME);
g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, nullptr );
// set the blink_time if there is a setting and it is reasonable
// else leave the default value
if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) )
aStyleSet.SetCursorBlinkTime( blink_time/2 );
}
else
aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
MouseSettings aMouseSettings = rSettings.GetMouseSettings();
int iDoubleClickTime, iDoubleClickDistance, iDragThreshold;
static const int MENU_POPUP_DELAY = 225;
g_object_get( pSettings,
"gtk-double-click-time", &iDoubleClickTime,
"gtk-double-click-distance", &iDoubleClickDistance,
"gtk-dnd-drag-threshold", &iDragThreshold,
nullptr );
aMouseSettings.SetDoubleClickTime( iDoubleClickTime );
aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance );
aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance );
aMouseSettings.SetStartDragWidth( iDragThreshold );
aMouseSettings.SetStartDragHeight( iDragThreshold );
aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY );
rSettings.SetMouseSettings( aMouseSettings );
gboolean primarybuttonwarps = false;
g_object_get( pSettings,
"gtk-primary-button-warps-slider", &primarybuttonwarps,
nullptr );
aStyleSet.SetPreferredUseImagesInMenus(false);
aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps);
// set scrollbar settings
gint slider_width = 14;
gint trough_border = 1;
gint min_slider_length = 21;
// Grab some button style attributes
gtk_style_context_get_style(mpVScrollbarStyle,
"slider-width", &slider_width,
"trough-border", &trough_border,
nullptr);
aStyleSet.SetScrollBarSize(slider_width + 2*trough_border);
if (gtk_check_version(3, 20, 0) == nullptr)
{
gtk_style_context_get(mpVScrollbarSliderStyle, gtk_style_context_get_state(mpVScrollbarSliderStyle),
"min-height", &min_slider_length,
nullptr);
aStyleSet.SetMinThumbSize(min_slider_length);
}
else
{
gtk_style_context_get_style(mpVScrollbarStyle,
"min-slider-length", &min_slider_length,
nullptr);
gint magic = trough_border ? 1 : 0;
aStyleSet.SetMinThumbSize(min_slider_length - magic);
}
// preferred icon style
gchar* pIconThemeName = nullptr;
gboolean bDarkIconTheme = false;
g_object_get(pSettings, "gtk-icon-theme-name", &pIconThemeName,
"gtk-application-prefer-dark-theme", &bDarkIconTheme,
nullptr );
OUString sIconThemeName(OUString::createFromAscii(pIconThemeName));
aStyleSet.SetPreferredIconTheme(sIconThemeName, bDarkIconTheme);
g_free( pIconThemeName );
aStyleSet.SetToolbarIconSize( ToolbarIconSize::Large );
// finally update the collected settings
rSettings.SetStyleSettings( aStyleSet );
#if OSL_DEBUG_LEVEL > 1
gchar* pThemeName = NULL;
g_object_get( pSettings, "gtk-theme-name", &pThemeName, nullptr );
fprintf( stderr, "Theme name is \"%s\"\n", pThemeName );
g_free(pThemeName);
#endif
}
bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
{
switch(nType)
{
case ControlType::Pushbutton:
case ControlType::Radiobutton:
case ControlType::Checkbox:
case ControlType::Progress:
case ControlType::ListNode:
case ControlType::ListNet:
if (nPart==ControlPart::Entire || nPart == ControlPart::Focus)
return true;
break;
case ControlType::Scrollbar:
if(nPart==ControlPart::DrawBackgroundHorz || nPart==ControlPart::DrawBackgroundVert ||
nPart==ControlPart::Entire || nPart==ControlPart::HasThreeButtons)
return true;
break;
case ControlType::Editbox:
case ControlType::MultilineEditbox:
if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture)
return true;
break;
case ControlType::Combobox:
if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons)
return true;
break;
case ControlType::Spinbox:
if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons || nPart == ControlPart::ButtonUp || nPart == ControlPart::ButtonDown)
return true;
break;
case ControlType::SpinButtons:
if (nPart==ControlPart::Entire || nPart==ControlPart::AllButtons)
return true;
break;
case ControlType::Frame:
case ControlType::WindowBackground:
return true;
case ControlType::TabItem:
case ControlType::TabHeader:
case ControlType::TabPane:
case ControlType::TabBody:
if(nPart==ControlPart::Entire || nPart==ControlPart::TabsDrawRtl)
return true;
break;
case ControlType::Listbox:
if (nPart==ControlPart::Entire || nPart==ControlPart::ListboxWindow || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::Focus)
return true;
break;
case ControlType::Toolbar:
if( nPart==ControlPart::Entire
// || nPart==ControlPart::DrawBackgroundHorz
// || nPart==ControlPart::DrawBackgroundVert
// || nPart==ControlPart::ThumbHorz
// || nPart==ControlPart::ThumbVert
|| nPart==ControlPart::Button
// || nPart==ControlPart::SeparatorHorz
|| nPart==ControlPart::SeparatorVert
)
return true;
break;
case ControlType::Menubar:
if (nPart==ControlPart::Entire || nPart==ControlPart::MenuItem)
return true;
break;
case ControlType::MenuPopup:
if (nPart==ControlPart::Entire
|| nPart==ControlPart::MenuItem
|| nPart==ControlPart::MenuItemCheckMark
|| nPart==ControlPart::MenuItemRadioMark
|| nPart==ControlPart::Separator
|| nPart==ControlPart::SubmenuArrow
)
return true;
break;
// case ControlType::Slider:
// if(nPart == ControlPart::TrackHorzArea || nPart == ControlPart::TrackVertArea)
// return true;
// break;
case ControlType::Fixedline:
if (nPart == ControlPart::SeparatorVert || nPart == ControlPart::SeparatorHorz)
return true;
break;
case ControlType::ListHeader:
if (nPart == ControlPart::Button || nPart == ControlPart::Arrow)
return true;
break;
default: break;
}
SAL_INFO("vcl.gtk", "Unhandled is native supported for Type:" << (int)nType << ", Part" << (int)nPart);
return false;
}
bool GtkSalGraphics::SupportsCairo() const
{
return true;
}
cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
{
return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(rSurface));
}
cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x, int y, int width, int height) const
{
return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(this, x, y, width, height));
}
void GtkSalGraphics::WidgetQueueDraw() const
{
//request gtk to sync the entire contents
gtk_widget_queue_draw(mpWindow);
}
namespace {
void getStyleContext(GtkStyleContext** style, GtkWidget* widget)
{
gtk_container_add(GTK_CONTAINER(gDumbContainer), widget);
*style = gtk_widget_get_style_context(widget);
g_object_ref(*style);
}
}
void GtkData::initNWF()
{
ImplSVData* pSVData = ImplGetSVData();
pSVData->maNWFData.mbFlatMenu = true;
pSVData->maNWFData.mbCheckBoxNeedsErase = true;
pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
pSVData->maNWFData.mbDDListBoxNoTextArea = true;
pSVData->maNWFData.mbNoFocusRects = true;
pSVData->maNWFData.mbNoFocusRectsForFlatButtons = true;
pSVData->maNWFData.mbAutoAccel = true;
pSVData->maNWFData.mbEnableAccel = true;
#if defined(GDK_WINDOWING_WAYLAND)
//gnome#768128 for the car crash that is wayland
//and floating dockable toolbars
GdkDisplay *pDisplay = gdk_display_get_default();
if (GDK_IS_WAYLAND_DISPLAY(pDisplay))
pSVData->maNWFData.mbDockingFloatsSupported = false;
#endif
}
void GtkData::deInitNWF()
{
if (gCacheWindow)
gtk_widget_destroy(gCacheWindow);
}
GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
: SvpSalGraphics(),
mpFrame( pFrame ),
mpWindow( pWindow )
{
if (style_loaded)
return;
style_loaded = true;
/* Load the GtkStyleContexts, it might be a bit slow, but usually,
* gtk apps create a lot of widgets at startup, so, it shouldn't be
* too slow */
gtk_widget_path_iter_set_object_nameFunc set_object_name =
reinterpret_cast<gtk_widget_path_iter_set_object_nameFunc>(osl_getAsciiFunctionSymbol(nullptr,
"gtk_widget_path_iter_set_object_name"));
gCacheWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gDumbContainer = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(gCacheWindow), gDumbContainer);
gtk_widget_realize(gDumbContainer);
gtk_widget_realize(gCacheWindow);
gEntryBox = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(gDumbContainer), gEntryBox);
mpWindowStyle = createStyleContext(set_object_name, GtkControlPart::ToplevelWindow);
mpEntryStyle = createStyleContext(set_object_name, GtkControlPart::Entry);
getStyleContext(&mpTextViewStyle, gtk_text_view_new());
mpButtonStyle = createStyleContext(set_object_name, GtkControlPart::Button);
mpLinkButtonStyle = createStyleContext(set_object_name, GtkControlPart::LinkButton);
GtkWidget* pToolbar = gtk_toolbar_new();
mpToolbarStyle = gtk_widget_get_style_context(pToolbar);
gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_TOOLBAR);
GtkToolItem *item = gtk_separator_tool_item_new();
gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
mpToolbarSeperatorStyle = gtk_widget_get_style_context(GTK_WIDGET(item));
GtkWidget *pButton = gtk_button_new();
item = gtk_tool_button_new(pButton, nullptr);
gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
mpToolButtonStyle = gtk_widget_get_style_context(GTK_WIDGET(pButton));
mpVScrollbarStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVertical);
mpVScrollbarContentsStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalContents);
mpVScrollbarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalTrough);
mpVScrollbarSliderStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalSlider);
mpVScrollbarButtonStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalButton);
mpHScrollbarStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontal);
mpHScrollbarContentsStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalContents);
mpHScrollbarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalTrough);
mpHScrollbarSliderStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalSlider);
mpHScrollbarButtonStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalButton);
mpCheckButtonStyle = createStyleContext(set_object_name, GtkControlPart::CheckButton);
mpCheckButtonCheckStyle = createStyleContext(set_object_name, GtkControlPart::CheckButtonCheck);
mpRadioButtonStyle = createStyleContext(set_object_name, GtkControlPart::RadioButton);
mpRadioButtonRadioStyle = createStyleContext(set_object_name, GtkControlPart::RadioButtonRadio);
/* Spinbutton */
gSpinBox = gtk_spin_button_new(nullptr, 0, 0);
gtk_container_add(GTK_CONTAINER(gDumbContainer), gSpinBox);
mpSpinStyle = createStyleContext(set_object_name, GtkControlPart::SpinButton);
mpSpinUpStyle = createStyleContext(set_object_name, GtkControlPart::SpinButtonUpButton);
mpSpinDownStyle = createStyleContext(set_object_name, GtkControlPart::SpinButtonDownButton);
/* NoteBook */
mpNotebookStyle = createStyleContext(set_object_name, GtkControlPart::Notebook);
mpNotebookStackStyle = createStyleContext(set_object_name, GtkControlPart::NotebookStack);
mpNotebookHeaderStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeader);
mpNotebookHeaderTabsStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabs);
mpNotebookHeaderTabsTabStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTab);
mpNotebookHeaderTabsTabLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabLabel);
mpNotebookHeaderTabsTabActiveLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabActiveLabel);
mpNotebookHeaderTabsTabHoverLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabHoverLabel);
/* Combobox */
gComboBox = gtk_combo_box_text_new_with_entry();
gtk_container_add(GTK_CONTAINER(gDumbContainer), gComboBox);
mpComboboxStyle = createStyleContext(set_object_name, GtkControlPart::Combobox);
mpComboboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBox);
mpComboboxEntryStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxEntry);
mpComboboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButton);
mpComboboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButtonBox);
mpComboboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButtonBoxArrow);
/* Listbox */
gListBox = gtk_combo_box_text_new();
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gListBox), "sample");
gtk_container_add(GTK_CONTAINER(gDumbContainer), gListBox);
mpListboxStyle = createStyleContext(set_object_name, GtkControlPart::Listbox);
mpListboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBox);
mpListboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButton);
mpListboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButtonBox);
mpListboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButtonBoxArrow);
/* Menu bar */
gMenuBarWidget = gtk_menu_bar_new();
gMenuItemMenuBarWidget = gtk_menu_item_new_with_label( "b" );
gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget), gMenuItemMenuBarWidget);
gtk_container_add(GTK_CONTAINER(gDumbContainer), gMenuBarWidget);
mpMenuBarStyle = createStyleContext(set_object_name, GtkControlPart::MenuBar);
mpMenuBarItemStyle = createStyleContext(set_object_name, GtkControlPart::MenuBarItem);
/* Menu */
mpMenuWindowStyle = createStyleContext(set_object_name, GtkControlPart::MenuWindow);
mpMenuStyle = createStyleContext(set_object_name, GtkControlPart::Menu);
GtkWidget *menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuItemMenuBarWidget), menu);
/* Menu Items */
gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), gCheckMenuItemWidget);
mpMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::MenuItem);
mpMenuItemLabelStyle = createStyleContext(set_object_name, GtkControlPart::MenuItemLabel);
mpMenuItemArrowStyle = createStyleContext(set_object_name, GtkControlPart::MenuItemArrow);
mpCheckMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::CheckMenuItem);
mpCheckMenuItemCheckStyle = createStyleContext(set_object_name, GtkControlPart::CheckMenuItemCheck);
mpRadioMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::RadioMenuItem);
mpRadioMenuItemRadioStyle = createStyleContext(set_object_name, GtkControlPart::RadioMenuItemRadio);
mpSeparatorMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::SeparatorMenuItem);
mpSeparatorMenuItemSeparatorStyle = createStyleContext(set_object_name, GtkControlPart::SeparatorMenuItemSeparator);
/* Frames */
mpFrameOutStyle = mpFrameInStyle = createStyleContext(set_object_name, GtkControlPart::FrameBorder);
getStyleContext(&mpFixedHoriLineStyle, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
getStyleContext(&mpFixedVertLineStyle, gtk_separator_new(GTK_ORIENTATION_VERTICAL));
/* Tree List */
gTreeViewWidget = gtk_tree_view_new();
gtk_container_add(GTK_CONTAINER(gDumbContainer), gTreeViewWidget);
GtkTreeViewColumn* firstTreeViewColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
GtkTreeViewColumn* middleTreeViewColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(middleTreeViewColumn, "M");
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
gtk_tree_view_set_expander_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
GtkTreeViewColumn* lastTreeViewColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
/* Use the middle column's header for our button */
GtkWidget* pTreeHeaderCellWidget = gtk_tree_view_column_get_button(middleTreeViewColumn);
mpTreeHeaderButtonStyle = gtk_widget_get_style_context(pTreeHeaderCellWidget);
/* Progress Bar */
mpProgressBarStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBar);
mpProgressBarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBar);
mpProgressBarProgressStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBarProgress);
gtk_widget_show_all(gDumbContainer);
}
void GtkSalGraphics::GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY)
{
char* pForceDpi;
if ((pForceDpi = getenv("SAL_FORCEDPI")))
{
OString sForceDPI(pForceDpi);
rDPIX = rDPIY = sForceDPI.toInt32();
return;
}
GdkScreen* pScreen = gtk_widget_get_screen(mpWindow);
double fResolution = -1.0;
g_object_get(pScreen, "resolution", &fResolution, nullptr);
int nScaleFactor = 1;
#if GTK_CHECK_VERSION(3, 10, 0)
nScaleFactor = gdk_window_get_scale_factor(widget_get_window(mpWindow));
#endif
if (fResolution > 0.0)
rDPIX = rDPIY = sal_Int32(fResolution * nScaleFactor);
else
rDPIX = rDPIY = 96;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */