Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 225e5e9

Browse files
author
Fraser J. Gordon
committed
Initial theming implementation for Linux using GTK
1 parent 2d23259 commit 225e5e9

File tree

5 files changed

+362
-2
lines changed

5 files changed

+362
-2
lines changed

engine/Makefile.kernel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ SOURCES=\
6666
objectprops.cpp objectpropsets.cpp variablevalue.cpp internal.cpp mcutility.cpp name.cpp \
6767
redraw.cpp tilecache.cpp tilecachesw.cpp syslnxregion.cpp fieldstyledtext.cpp paragrafattr.cpp \
6868
fonttable.cpp fieldrtf.cpp fieldhtml.cpp stackcache.cpp quicktime.cpp \
69-
sysunxthreads.cpp, stacktile.cpp
69+
sysunxthreads.cpp, stacktile.cpp \
70+
linux-theme.cpp
7071

7172
linuxstubs.cpp: src/linux.stubs
7273
../prebuilt/bin/Revolution.lnx "../tools/weak_stub_maker.lc" <./src/linux.stubs >./src/linuxstubs.cpp

engine/engine.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@
15401540
4DFFC7DF13DD8A91006233A4 /* sysunxnetwork.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sysunxnetwork.cpp; path = src/sysunxnetwork.cpp; sourceTree = "<group>"; };
15411541
4DFFC7E613DD8AB9006233A4 /* objectpropsets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = objectpropsets.cpp; path = src/objectpropsets.cpp; sourceTree = "<group>"; };
15421542
4DFFC7EE13DD8AFC006233A4 /* name.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = name.cpp; path = src/name.cpp; sourceTree = "<group>"; };
1543+
7269EC371A13D1DE000723DB /* linux-theme.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "linux-theme.cpp"; path = "src/linux-theme.cpp"; sourceTree = "<group>"; };
15431544
72B67C501A0BBDF600BB2594 /* mac-theme.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "mac-theme.mm"; path = "src/mac-theme.mm"; sourceTree = "<group>"; };
15441545
76CCAA7B198003B000C79271 /* mac-qt-recorder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "mac-qt-recorder.mm"; path = "src/mac-qt-recorder.mm"; sourceTree = "<group>"; };
15451546
76CCAA7D19800EFE00C79271 /* platform-recorder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "platform-recorder.cpp"; path = "src/platform-recorder.cpp"; sourceTree = "<group>"; };
@@ -2240,6 +2241,7 @@
22402241
4D77411A1226B930001C9150 /* lnxtransfer.h */,
22412242
4DFECFE413CEF2DB00288995 /* lnxprefix.h */,
22422243
4DFED11E13CEFC5400288995 /* lnxtheme.h */,
2244+
7269EC371A13D1DE000723DB /* linux-theme.cpp */,
22432245
);
22442246
name = "Desktop - Linux";
22452247
sourceTree = "<group>";

engine/src/globals.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ bool X_open(int argc, char *argv[], char *envp[])
10161016
MCttfont = "Helvetica Neue";
10171017
}*/
10181018
#elif defined(TARGET_PLATFORM_LINUX)
1019-
MCdispatcher -> setfontattrs("Helvetica", 12, FA_DEFAULT_STYLE);
1019+
//MCdispatcher -> setfontattrs("Helvetica", 12, FA_DEFAULT_STYLE);
10201020
#else
10211021
MCdispatcher -> setfontattrs(DEFAULT_TEXT_FONT, DEFAULT_TEXT_SIZE, FA_DEFAULT_STYLE);
10221022
#endif

engine/src/linux-theme.cpp

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
/* Copyright (C) 2014 Runtime Revolution Ltd.
2+
3+
This file is part of LiveCode.
4+
5+
LiveCode is free software; you can redistribute it and/or modify it under
6+
the terms of the GNU General Public License v3 as published by the Free
7+
Software Foundation.
8+
9+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
10+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
16+
17+
18+
#include "platform.h"
19+
20+
#include "globdefs.h"
21+
#include "objdefs.h"
22+
#include "parsedef.h"
23+
#include "filedefs.h"
24+
#include "mcstring.h"
25+
#include "globals.h"
26+
#include "mctheme.h"
27+
#include "util.h"
28+
#include "object.h"
29+
#include "stack.h"
30+
#include "font.h"
31+
32+
33+
#include <gtk/gtk.h>
34+
35+
36+
// Cached styles for various widget types
37+
static GtkStyle* s_styles[kMCPlatformControlTypeMessageBox+1];
38+
39+
// Cached widgets (for style updates)
40+
static GtkWidget* s_widgets[kMCPlatformControlTypeMessageBox+1];
41+
42+
// Container for widgets
43+
static GtkWidget* s_widget_container = NULL;
44+
45+
46+
// Creates a GtkWidget corresponding to the requested control type
47+
static GtkWidget* getWidgetForControlType(MCPlatformControlType p_type, MCPlatformControlPart p_part)
48+
{
49+
// Ensure that our container widget exists
50+
if (s_widget_container == NULL)
51+
{
52+
gtk_init(NULL, NULL);
53+
54+
// Create a new window
55+
GtkWidget* t_window;
56+
t_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
57+
s_widgets[kMCPlatformControlTypeGlobal] = t_window;
58+
59+
// Ensure it actually exists
60+
gtk_widget_realize(t_window);
61+
62+
// Create a container to store our widgets and put it in the window
63+
s_widget_container = gtk_fixed_new();
64+
gtk_container_add(GTK_CONTAINER(t_window), GTK_WIDGET(s_widget_container));
65+
gtk_widget_realize(GTK_WIDGET(s_widget_container));
66+
}
67+
68+
// Return the existing widget if possible
69+
if (s_widgets[p_type] != NULL)
70+
{
71+
g_object_ref(s_widgets[p_type]);
72+
return s_widgets[p_type];
73+
}
74+
75+
GtkWidget* t_the_widget;
76+
t_the_widget = NULL;
77+
78+
bool t_suppress_add;
79+
t_suppress_add = false;
80+
81+
switch (p_type)
82+
{
83+
case kMCPlatformControlTypeGlobal:
84+
t_the_widget = s_widgets[kMCPlatformControlTypeGlobal];
85+
t_suppress_add = true;
86+
break;
87+
88+
case kMCPlatformControlTypeButton:
89+
t_the_widget = gtk_button_new();
90+
break;
91+
92+
case kMCPlatformControlTypeCheckbox:
93+
t_the_widget = gtk_check_button_new();
94+
break;
95+
96+
case kMCPlatformControlTypeRadioButton:
97+
t_the_widget = gtk_radio_button_new(NULL);
98+
break;
99+
100+
case kMCPlatformControlTypeTabButton:
101+
case kMCPlatformControlTypeTabPane:
102+
t_the_widget = gtk_notebook_new();
103+
break;
104+
105+
case kMCPlatformControlTypeLabel:
106+
t_the_widget = gtk_label_new("LiveCode");
107+
break;
108+
109+
case kMCPlatformControlTypeInputField:
110+
t_the_widget = gtk_entry_new();
111+
break;
112+
113+
case kMCPlatformControlTypeList:
114+
t_the_widget = gtk_tree_view_new();
115+
break;
116+
117+
case kMCPlatformControlTypeMenu:
118+
t_the_widget = gtk_menu_item_new();
119+
break;
120+
121+
case kMCPlatformControlTypeMenuItem:
122+
t_the_widget = gtk_menu_item_new();
123+
break;
124+
125+
case kMCPlatformControlTypeOptionMenu:
126+
t_the_widget = gtk_combo_box_new();
127+
break;
128+
129+
case kMCPlatformControlTypePulldownMenu:
130+
t_the_widget = gtk_menu_item_new();
131+
break;
132+
133+
case kMCPlatformControlTypeComboBox:
134+
t_the_widget = gtk_combo_box_new_with_entry();
135+
break;
136+
137+
case kMCPlatformControlTypePopupMenu:
138+
t_the_widget = gtk_menu_item_new();
139+
break;
140+
141+
case kMCPlatformControlTypeProgressBar:
142+
t_the_widget = gtk_progress_bar_new();
143+
break;
144+
145+
case kMCPlatformControlTypeScrollBar:
146+
t_the_widget = gtk_vscrollbar_new(NULL);
147+
break;
148+
149+
case kMCPlatformControlTypeSlider:
150+
break;
151+
152+
case kMCPlatformControlTypeSpinArrows:
153+
break;
154+
155+
case kMCPlatformControlTypeWindow:
156+
t_the_widget = s_widgets[kMCPlatformControlTypeGlobal];
157+
g_object_ref(t_the_widget);
158+
t_suppress_add = true;
159+
break;
160+
161+
case kMCPlatformControlTypeMessageBox:
162+
break;
163+
}
164+
165+
if (t_the_widget == NULL)
166+
return NULL;
167+
168+
s_widgets[p_type] = t_the_widget;
169+
170+
// Add to the container and realize so that styles get set up correctly
171+
if (!t_suppress_add)
172+
gtk_fixed_put(GTK_FIXED(s_widget_container), t_the_widget, 0, 0);
173+
gtk_widget_realize(t_the_widget);
174+
175+
g_object_ref(t_the_widget);
176+
return t_the_widget;
177+
}
178+
179+
// Gets the style for the given control type
180+
static GtkStyle* getStyleForControlType(MCPlatformControlType p_type, MCPlatformControlPart p_part)
181+
{
182+
if (s_styles[p_type] == NULL)
183+
{
184+
GtkWidget* t_widget;
185+
t_widget = getWidgetForControlType(p_type, p_part);
186+
187+
if (t_widget != NULL)
188+
{
189+
s_styles[p_type] = gtk_widget_get_style(t_widget);
190+
g_object_unref(t_widget);
191+
}
192+
}
193+
194+
return s_styles[p_type];
195+
}
196+
197+
198+
bool MCPlatformGetControlThemePropInteger(MCPlatformControlType p_type, MCPlatformControlPart p_part, MCPlatformControlState p_state, MCPlatformThemeProperty p_prop, int& r_int)
199+
{
200+
GtkStyle* t_style;
201+
t_style = getStyleForControlType(p_type, p_part);
202+
if (t_style == NULL)
203+
return false;
204+
205+
bool t_found;
206+
t_found = false;
207+
208+
switch (p_prop)
209+
{
210+
case kMCPlatformThemePropertyTextSize:
211+
t_found = true;
212+
r_int = pango_font_description_get_size(t_style->font_desc)/PANGO_SCALE;
213+
break;
214+
215+
default:
216+
break;
217+
}
218+
219+
return t_found;
220+
}
221+
222+
bool MCPlatformGetControlThemePropColor(MCPlatformControlType p_type, MCPlatformControlPart p_part, MCPlatformControlState p_state, MCPlatformThemeProperty p_prop, MCColor& r_color)
223+
{
224+
GtkStyle* t_style;
225+
t_style = getStyleForControlType(p_type, p_part);
226+
if (t_style == NULL)
227+
return false;
228+
229+
bool t_found;
230+
t_found = false;
231+
232+
GtkStateType t_gtk_state;
233+
if (p_state & kMCPlatformControlStateDisabled)
234+
t_gtk_state = GTK_STATE_INSENSITIVE;
235+
else if (p_state & kMCPlatformControlStateSelected)
236+
t_gtk_state = GTK_STATE_SELECTED;
237+
else if (p_state & kMCPlatformControlStatePressed)
238+
t_gtk_state = GTK_STATE_ACTIVE;
239+
else if (p_state & kMCPlatformControlStateMouseOver)
240+
t_gtk_state = GTK_STATE_PRELIGHT;
241+
else
242+
t_gtk_state = GTK_STATE_NORMAL;
243+
244+
GdkColor t_color;
245+
246+
switch (p_prop)
247+
{
248+
case kMCPlatformThemePropertyTextColor:
249+
t_found = true;
250+
t_color = t_style->text[t_gtk_state];
251+
break;
252+
253+
case kMCPlatformThemePropertyBackgroundColor:
254+
{
255+
t_found = true;
256+
switch (p_type)
257+
{
258+
// We want the base colour, not background, for fields
259+
case kMCPlatformControlTypeInputField:
260+
case kMCPlatformControlTypeList:
261+
t_color = t_style->base[t_gtk_state];
262+
break;
263+
264+
// Suppress the disabled state to avoid some weird-looking menus
265+
case kMCPlatformControlTypeMenu:
266+
case kMCPlatformControlTypeOptionMenu:
267+
case kMCPlatformControlTypePopupMenu:
268+
case kMCPlatformControlTypeMenuItem:
269+
if (t_gtk_state == GTK_STATE_INSENSITIVE)
270+
t_gtk_state = GTK_STATE_NORMAL;
271+
/* FALLTHROUGH */
272+
273+
default:
274+
t_color = t_style->bg[t_gtk_state];
275+
break;
276+
}
277+
break;
278+
}
279+
280+
case kMCPlatformThemePropertyShadowColor:
281+
t_found = true;
282+
t_color = t_style->dark[t_gtk_state];
283+
break;
284+
285+
case kMCPlatformThemePropertyBorderColor:
286+
t_found = true;
287+
t_color = t_style->dark[t_gtk_state];
288+
break;
289+
290+
case kMCPlatformThemePropertyFocusColor:
291+
break;
292+
}
293+
294+
if (t_found)
295+
{
296+
r_color.red = t_color.red;
297+
r_color.green = t_color.green;
298+
r_color.blue = t_color.blue;
299+
300+
MCscreen->alloccolor(r_color);
301+
}
302+
303+
return t_found;
304+
}
305+
306+
bool MCPlatformGetControlThemePropFont(MCPlatformControlType p_type, MCPlatformControlPart p_part, MCPlatformControlState p_state, MCPlatformThemeProperty p_prop, MCFontRef& r_font)
307+
{
308+
GtkStyle* t_style;
309+
t_style = getStyleForControlType(p_type, p_part);
310+
if (t_style == NULL)
311+
return false;
312+
313+
bool t_found;
314+
t_found = false;
315+
316+
const PangoFontDescription* t_pango;
317+
t_pango = NULL;
318+
319+
switch (p_prop)
320+
{
321+
case kMCPlatformThemePropertyTextFont:
322+
t_found = true;
323+
t_pango = t_style->font_desc;
324+
break;
325+
326+
default:
327+
break;
328+
}
329+
330+
if (!t_found)
331+
return false;
332+
333+
MCFontRef t_font_ref;
334+
MCNameRef t_font_name;
335+
t_found = MCNameCreateWithCString(pango_font_description_get_family(t_pango), t_font_name);
336+
if (t_found)
337+
t_found = MCFontCreate(t_font_name, 0, pango_font_description_get_size(t_pango)/PANGO_SCALE, t_font_ref);
338+
if (t_found)
339+
r_font = t_font_ref;
340+
MCNameDelete(t_font_name);
341+
342+
return t_found;
343+
}

0 commit comments

Comments
 (0)