Skip to content

Commit fb0e438

Browse files
committed
Merge pull request livecode#3447 from livecodefraser/feature-native_themes
Use more native-looking themes on desktop platforms by default
2 parents 6fcb626 + fd75fd7 commit fb0e438

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+823
-159
lines changed

config/win32.gypi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@
123123
'_CRT_SECURE_NO_DEPRECATE',
124124
'_CRT_DISABLE_PERFCRIT_LOCKS',
125125
'__LITTLE_ENDIAN__',
126+
'WINVER=0x0501', # Windows XP
127+
'_WIN32_WINNT=0x0501', # Windows XP
126128
],
127129

128130
'target_conditions':
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Name: theme
2+
3+
Type: property
4+
5+
Syntax: set the theme of tObject to tThemeName
6+
7+
Summary: Specifies the theme to use when drawing the control.
8+
9+
Introduced: 8.0
10+
11+
OS: mac,windows,linux,ios,android
12+
13+
Platforms: desktop,server,web,mobile
14+
15+
Example:
16+
set the theme of this stack to "native"
17+
18+
Value (string): The <theme> of an object or control is a name identifying the style to use when drawing it.
19+
20+
Description:
21+
Use the <theme> property to control the general appearance of an object or control. It can be set on any object, including cards, stacks and controls. The currently supported values are "native" and "legacy". For an appearance that matches native apps for the platform an app is running on, use "native". The "legacy" setting preserves the appearance of older versions of LiveCode and is provided for backwards-compatibility.
22+
23+
References: themeClass (property)
24+
25+
Tags: ui
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Name: themeClass
2+
3+
Type: property
4+
5+
Syntax: set the themeClass of tObject to tThemeClass
6+
7+
Summary: Specifies which set of theming parameters should be used for an object.
8+
9+
Introduced: 8.0
10+
11+
OS: mac,windows,linux,ios,android
12+
13+
Platforms: desktop,server,web,mobile
14+
15+
Example:
16+
set the themeClass of field "mylabel" to "label"
17+
18+
Value (string): The <themeClass> of an object or control is what kind of object to treat it as for UI theming purposes.
19+
20+
Description:
21+
Use the <themeClass> property of an object or control to change which set of theming parameters it uses. These parameters include fonts, colors and sizes. For example, setting the <themeClass> of a field to "label" will cause it to use the fonts and colors of a label rather than a text entry box.
22+
23+
If no <themeClass> is specified, the engine will auto-detect the appropriate type based on the properties of the object. To retrieve this auto-detected type when the property is empty use <the effective themeClass>.
24+
25+
Unlike many other appearance-related properties, the <themeClass> property is not inherited.
26+
27+
References: theme (property)
28+
29+
Tags: ui
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# More native-looking stack theming
2+
3+
The default appearance of stacks on desktop platforms has been updated to more
4+
closely match the appearance of native apps. This particularly affects OSX
5+
and Linux apps.
6+
7+
One effect of this is that the default text size is now different for different
8+
types of controls. As this may cause layout issues for existing stacks, it is
9+
possible to set the theme property of a stack, card or control to "legacy" to
10+
restore the old behavior. The new behavior can be explicitly requested for an
11+
object by setting the theme to "native".

engine/engine-sources.gypi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@
541541
'<(SHARED_INTERMEDIATE_DIR)/src/quicktimestubs.mac.cpp',
542542

543543
# Group "Desktop - Mac"
544-
'src/coretextfonts.cpp',
544+
'src/coretextfonts.mm',
545545
'src/osxflst.cpp',
546546

547547
# Group "Desktop - Linux"
@@ -1150,7 +1150,6 @@
11501150
'sources!':
11511151
[
11521152
'src/cgimageutil.cpp',
1153-
'src/coretextfonts.cpp',
11541153
'src/syscfdate.cpp',
11551154
'src/tilecachecg.cpp',
11561155
],

engine/src/button.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
5252

5353
#include "exec.h"
5454

55-
uint2 MCButton::mnemonicoffset = 2;
55+
uint2 MCButton::mnemonicoffset = 1;
5656
MCRectangle MCButton::optionrect = {0, 0, 12, 8};
5757
uint4 MCButton::clicktime;
5858
uint2 MCButton::menubuttonheight = 4;
@@ -3408,11 +3408,13 @@ class ButtonMenuCallback : public IParseMenuCallback
34083408

34093409
newbutton->menubutton = parent->menubutton;
34103410
newbutton->menucontrol = MENUCONTROL_ITEM;
3411+
newbutton->m_theme_type = kMCPlatformControlTypeMenu;
34113412
if (MCNameGetCharAtIndex(newbutton -> getname(), 0) == '-')
34123413
{
34133414
newbutton->rect.height = 2;
34143415
newbutton->flags = DIVIDER_FLAGS;
34153416
newbutton->menucontrol = MENUCONTROL_SEPARATOR;
3417+
newbutton->m_theme_type = kMCPlatformControlTypeMenu;
34163418
if (MCcurtheme && MCcurtheme->getthemeid() == LF_NATIVEWIN)
34173419
{
34183420
newbutton->rect.height = 1;
@@ -4835,8 +4837,18 @@ IO_stat MCButton::load(IO_handle stream, uint32_t version)
48354837
MCPlatformControlType MCButton::getcontroltype()
48364838
{
48374839
MCPlatformControlType t_type;
4838-
t_type = kMCPlatformControlTypeButton;
4839-
if (getstyleint(flags) == F_MENU)
4840+
t_type = MCObject::getcontroltype();
4841+
4842+
if (t_type != kMCPlatformControlTypeGeneric)
4843+
return t_type;
4844+
else
4845+
t_type = kMCPlatformControlTypeButton;
4846+
4847+
if (getstyleint(flags) == F_CHECK)
4848+
t_type = kMCPlatformControlTypeCheckbox;
4849+
else if (getstyleint(flags) == F_RADIO)
4850+
t_type = kMCPlatformControlTypeRadioButton;
4851+
else if (getstyleint(flags) == F_MENU || menucontrol != MENUCONTROL_NONE)
48404852
{
48414853
t_type = kMCPlatformControlTypeMenu;
48424854
switch (menumode)
@@ -4857,6 +4869,10 @@ MCPlatformControlType MCButton::getcontroltype()
48574869
t_type = kMCPlatformControlTypePulldownMenu;
48584870
break;
48594871

4872+
case WM_TOP_LEVEL:
4873+
t_type = kMCPlatformControlTypeTabPane;
4874+
break;
4875+
48604876
default:
48614877
break;
48624878
}

engine/src/buttondraw.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -676,19 +676,27 @@ void MCButton::drawlabel(MCDC *dc, int2 sx, int sy, uint2 twidth, const MCRectan
676676
fascent = MCFontGetAscent(m_font);
677677
dc->drawline(sx, sy - (fascent >> 1), sx + twidth, sy - (fascent >> 1));
678678
}
679-
if (!IsMacLF() && mnemonic)
679+
if (!IsMacLF() && mnemonic
680+
&& (gettheme() == kMCInterfaceThemeLegacy || (MCscreen->querymods() & MS_ALT)))
680681
{
681682
if (p_mnemonic > 0)
682683
{
683684
MCRange t_before = MCRangeMake(0, mnemonic - 1);
684685
MCRange t_letter = MCRangeMake(mnemonic - 1, 1);
685-
686-
// MM-2014-04-16: [[ Bug 11964 ]] Pass through the transform of the stack to make sure the measurment is correct for scaled text.
686+
687+
// MM-2014-04-16: [[ Bug 11964 ]] Pass through the transform of the stack to make sure the measurment is correct for scaled text.
687688
int32_t mstart = sx + MCFontMeasureTextSubstring(m_font, p_label, t_before, getstack() -> getdevicetransform());
688689
int32_t mwidth = MCFontMeasureTextSubstring(m_font, p_label, t_letter, getstack() -> getdevicetransform());
689690

691+
#ifdef TARGET_PLATFORM_WINDOWS
692+
// No idea why this fudge-factor is required on Windows...
693+
// Without it, the mnemonic underlines are drawn too far
694+
// to the left, mis-aligning them with the mnemonic letter.
695+
mstart -= 1;
696+
#endif
697+
690698
sy += mnemonicoffset;
691-
dc->drawline(mstart, sy, mstart + mwidth, sy);
699+
dc->drawline(mstart, sy, mstart + mwidth - 1, sy);
692700
}
693701
}
694702
}

engine/src/card.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,11 +3736,11 @@ void MCCard::unlockshape(MCObjectShape& p_shape)
37363736

37373737
// MW-2012-02-14: [[ FontRefs ]] Update the card's font and then (if necessary) recurse
37383738
// through all controls to do the same.
3739-
bool MCCard::recomputefonts(MCFontRef p_parent_font)
3739+
bool MCCard::recomputefonts(MCFontRef p_parent_font, bool p_force)
37403740
{
37413741
// First update the font referenced by the card object. If this doesn't change
37423742
// then none of the card's children will have either.
3743-
if (!MCObject::recomputefonts(p_parent_font))
3743+
if (!MCObject::recomputefonts(p_parent_font, p_force))
37443744
return false;
37453745

37463746
// Now iterate through all objects on the card, keeping track of whether any
@@ -3754,7 +3754,7 @@ bool MCCard::recomputefonts(MCFontRef p_parent_font)
37543754
t_objptr = objptrs;
37553755
do
37563756
{
3757-
if (t_objptr -> getref() -> recomputefonts(m_font))
3757+
if (t_objptr -> getref() -> recomputefonts(m_font, p_force))
37583758
t_changed = true;
37593759
t_objptr = t_objptr -> next();
37603760
}
@@ -3793,7 +3793,13 @@ void MCCard::scheduledelete(bool p_is_child)
37933793

37943794
MCPlatformControlType MCCard::getcontroltype()
37953795
{
3796-
return kMCPlatformControlTypeWindow;
3796+
MCPlatformControlType t_type;
3797+
t_type = MCObject::getcontroltype();
3798+
3799+
if (t_type != kMCPlatformControlTypeGeneric)
3800+
return t_type;
3801+
else
3802+
return kMCPlatformControlTypeWindow;
37973803
}
37983804

37993805
MCPlatformControlPart MCCard::getcontrolsubpart()

engine/src/card.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class MCCard : public MCObject
101101
virtual void unlockshape(MCObjectShape& shape);
102102

103103
// MW-2012-02-14: [[ FontRefs ]] Recompute the font inheritence hierarchy.
104-
virtual bool recomputefonts(MCFontRef parent_font);
104+
virtual bool recomputefonts(MCFontRef parent_font, bool force);
105105

106106
// MW-2012-06-08: [[ Relayer ]] Move a control to before target.
107107
virtual void relayercontrol(MCControl *p_source, MCControl *p_target);
@@ -335,7 +335,7 @@ class MCCard : public MCObject
335335
virtual void SetTextFont(MCExecContext& ctxt, MCStringRef font);
336336
virtual void SetTextSize(MCExecContext& ctxt, uinteger_t* size);
337337
virtual void SetTextStyle(MCExecContext& ctxt, const MCInterfaceTextStyle& p_style);
338-
338+
virtual void SetTheme(MCExecContext& ctxt, intenum_t p_theme);
339339
};
340340

341341
#endif
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#import <CoreText/CoreText.h>
3131
#else
3232
#import <ApplicationServices/ApplicationServices.h>
33+
#import <AppKit/NSFont.h>
3334
#endif
3435

3536
#ifdef TARGET_SUBPLATFORM_IPHONE
@@ -75,6 +76,43 @@ void ios_clear_font_mapping(void)
7576
}
7677
#endif
7778

79+
#ifndef TARGET_SUBPLATFORM_IPHONE
80+
static void* coretext_font_create_system(uint32_t p_size)
81+
{
82+
return [[NSFont systemFontOfSize: p_size] retain];
83+
}
84+
85+
static void* coretext_font_create_system_bold(uint32_t p_size)
86+
{
87+
return [[NSFont boldSystemFontOfSize: p_size] retain];
88+
}
89+
90+
static void* coretext_font_create_content(uint32_t p_size)
91+
{
92+
return [[NSFont controlContentFontOfSize: p_size] retain];
93+
}
94+
95+
static void* coretext_font_create_menu(uint32_t p_size)
96+
{
97+
return [[NSFont menuFontOfSize: p_size] retain];
98+
}
99+
100+
static void* coretext_font_create_message(uint32_t p_size)
101+
{
102+
return [[NSFont messageFontOfSize: p_size] retain];
103+
}
104+
105+
static void* coretext_font_create_tooltip(uint32_t p_size)
106+
{
107+
return [[NSFont toolTipsFontOfSize: p_size] retain];
108+
}
109+
110+
static void* coretext_font_create_user(uint32_t p_size)
111+
{
112+
return [[NSFont userFontOfSize: p_size] retain];
113+
}
114+
#endif
115+
78116
static void *coretext_font_create_with_name_and_size(MCStringRef p_name, uint32_t p_size)
79117
{
80118
/*CFStringRef t_name;
@@ -94,6 +132,24 @@ static void *coretext_font_create_with_name_and_size(MCStringRef p_name, uint32_
94132
bool t_success;
95133
t_success = true;
96134

135+
#ifndef TARGET_SUBPLATFORM_IPHONE
136+
// On OSX, use the special "system" and "user" fonts where requested. OSX
137+
// doesn't actually let you get the display-optimised fonts by name (in
138+
// particular, the optimised Helvetica Neue and San Fransisco fonts).
139+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - System", kMCStringOptionCompareCaseless))
140+
return coretext_font_create_system(p_size);
141+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - User", kMCStringOptionCompareCaseless))
142+
return coretext_font_create_user(p_size);
143+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - Content", kMCStringOptionCompareCaseless))
144+
return coretext_font_create_content(p_size);
145+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - Menu", kMCStringOptionCompareCaseless))
146+
return coretext_font_create_menu(p_size);
147+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - Message", kMCStringOptionCompareCaseless))
148+
return coretext_font_create_message(p_size);
149+
if (MCStringIsEqualToCString(p_name, "Aqua UI Font - Tooltip", kMCStringOptionCompareCaseless))
150+
return coretext_font_create_tooltip(p_size);
151+
#endif
152+
97153
// SN-2015-02-16: [[ iOS Font mapping ]] On iOS, try to fetch the mapped
98154
// if one exists.
99155
// Defaults to the given name if no one matches, or on MacOS

0 commit comments

Comments
 (0)