1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 namespace juce
27 {
28 
getTypefaceForFontFromLookAndFeel(const Font & font)29 static Typeface::Ptr getTypefaceForFontFromLookAndFeel (const Font& font)
30 {
31     return LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (font);
32 }
33 
34 using GetTypefaceForFont = Typeface::Ptr (*)(const Font&);
35 extern GetTypefaceForFont juce_getTypefaceForFont;
36 
37 //==============================================================================
LookAndFeel()38 LookAndFeel::LookAndFeel()
39 {
40     /* if this fails it means you're trying to create a LookAndFeel object before
41        the static Colours have been initialised. That ain't gonna work. It probably
42        means that you're using a static LookAndFeel object and that your compiler has
43        decided to initialise it before the Colours class.
44     */
45     jassert (Colours::white == Colour (0xffffffff));
46 
47     juce_getTypefaceForFont = getTypefaceForFontFromLookAndFeel;
48 }
49 
~LookAndFeel()50 LookAndFeel::~LookAndFeel()
51 {
52     /* This assertion is triggered if you try to delete a LookAndFeel object while something
53        is still using it!
54 
55        Reasons may be:
56          - it's still being used as the default LookAndFeel; or
57          - it's set as a Component's current lookandfeel; or
58          - there's a WeakReference to it somewhere else in your code
59 
60        Generally the fix for this will be to make sure you call
61        Component::setLookandFeel (nullptr) on any components that were still using
62        it before you delete it, or call LookAndFeel::setDefaultLookAndFeel (nullptr)
63        if you had set it up to be the default one. This assertion can also be avoided by
64        declaring your LookAndFeel object before any of the Components that use it as
65        the Components will be destroyed before the LookAndFeel.
66 
67        Deleting a LookAndFeel is unlikely to cause a crash since most things will use a
68        safe WeakReference to it, but it could cause some unexpected graphical behaviour,
69        so it's advisable to clear up any references before destroying them!
70     */
71     jassert (masterReference.getNumActiveWeakReferences() == 0
72               || (masterReference.getNumActiveWeakReferences() == 1
73                    && this == &getDefaultLookAndFeel()));
74 }
75 
76 //==============================================================================
findColour(int colourID) const77 Colour LookAndFeel::findColour (int colourID) const noexcept
78 {
79     const ColourSetting c = { colourID, Colour() };
80     auto index = colours.indexOf (c);
81 
82     if (index >= 0)
83         return colours[index].colour;
84 
85     jassertfalse;
86     return Colours::black;
87 }
88 
setColour(int colourID,Colour newColour)89 void LookAndFeel::setColour (int colourID, Colour newColour) noexcept
90 {
91     const ColourSetting c = { colourID, newColour };
92     auto index = colours.indexOf (c);
93 
94     if (index >= 0)
95         colours.getReference (index).colour = newColour;
96     else
97         colours.add (c);
98 }
99 
isColourSpecified(const int colourID) const100 bool LookAndFeel::isColourSpecified (const int colourID) const noexcept
101 {
102     const ColourSetting c = { colourID, Colour() };
103     return colours.contains (c);
104 }
105 
106 //==============================================================================
getDefaultLookAndFeel()107 LookAndFeel& LookAndFeel::getDefaultLookAndFeel() noexcept
108 {
109     return Desktop::getInstance().getDefaultLookAndFeel();
110 }
111 
setDefaultLookAndFeel(LookAndFeel * newDefaultLookAndFeel)112 void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) noexcept
113 {
114     Desktop::getInstance().setDefaultLookAndFeel (newDefaultLookAndFeel);
115 }
116 
117 //==============================================================================
getTypefaceForFont(const Font & font)118 Typeface::Ptr LookAndFeel::getTypefaceForFont (const Font& font)
119 {
120     if (font.getTypefaceName() == Font::getDefaultSansSerifFontName())
121     {
122         if (defaultTypeface != nullptr)
123             return defaultTypeface;
124 
125         if (defaultSans.isNotEmpty())
126         {
127             Font f (font);
128             f.setTypefaceName (defaultSans);
129             return Typeface::createSystemTypefaceFor (f);
130         }
131     }
132 
133     return Font::getDefaultTypefaceForFont (font);
134 }
135 
setDefaultSansSerifTypeface(Typeface::Ptr newDefaultTypeface)136 void LookAndFeel::setDefaultSansSerifTypeface (Typeface::Ptr newDefaultTypeface)
137 {
138     if (defaultTypeface != newDefaultTypeface)
139     {
140         defaultTypeface = newDefaultTypeface;
141         Typeface::clearTypefaceCache();
142     }
143 }
144 
setDefaultSansSerifTypefaceName(const String & newName)145 void LookAndFeel::setDefaultSansSerifTypefaceName (const String& newName)
146 {
147     if (defaultSans != newName)
148     {
149         defaultTypeface.reset();
150         Typeface::clearTypefaceCache();
151         defaultSans = newName;
152     }
153 }
154 
155 //==============================================================================
getMouseCursorFor(Component & component)156 MouseCursor LookAndFeel::getMouseCursorFor (Component& component)
157 {
158     auto cursor = component.getMouseCursor();
159 
160     for (auto* parent = component.getParentComponent();
161          parent != nullptr && cursor == MouseCursor::ParentCursor;
162          parent = parent->getParentComponent())
163     {
164         cursor = parent->getMouseCursor();
165     }
166 
167     return cursor;
168 }
169 
createGraphicsContext(const Image & imageToRenderOn,Point<int> origin,const RectangleList<int> & initialClip)170 std::unique_ptr<LowLevelGraphicsContext> LookAndFeel::createGraphicsContext (const Image& imageToRenderOn,
171                                                                              Point<int> origin,
172                                                                              const RectangleList<int>& initialClip)
173 {
174     return std::make_unique<LowLevelGraphicsSoftwareRenderer> (imageToRenderOn, origin, initialClip);
175 }
176 
177 //==============================================================================
setUsingNativeAlertWindows(bool shouldUseNativeAlerts)178 void LookAndFeel::setUsingNativeAlertWindows (bool shouldUseNativeAlerts)
179 {
180     useNativeAlertWindows = shouldUseNativeAlerts;
181 }
182 
isUsingNativeAlertWindows()183 bool LookAndFeel::isUsingNativeAlertWindows()
184 {
185    #if JUCE_LINUX
186     return false; // not available currently..
187    #else
188     return useNativeAlertWindows;
189    #endif
190 }
191 
192 } // namespace juce
193