1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** \file
3 * Desktop widget implementation.
4 */
5 /* Authors:
6 * Jon A. Cruz <jon@joncruz.org>
7 *
8 * Copyright (C) 2010 Jon A. Cruz
9 *
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13 #include <vector>
14 #include "widgets/desktop-widget.h"
15
16 #include "uxmanager.h"
17 #include "desktop.h"
18 #include "ui/monitor.h"
19 #include "widgets/toolbox.h"
20
21 class TrackItem
22 {
23 public:
TrackItem()24 TrackItem() :
25 destroyConn(),
26 boxes()
27 {}
28
29 sigc::connection destroyConn;
30 std::vector<GtkWidget*> boxes;
31 };
32
33 static std::vector<SPDesktop*> desktops;
34 static std::vector<SPDesktopWidget*> dtws;
35 static std::map<SPDesktop*, TrackItem> trackedBoxes;
36
37
38 namespace {
39
desktopDestructHandler(SPDesktop * desktop)40 void desktopDestructHandler(SPDesktop *desktop)
41 {
42 std::map<SPDesktop*, TrackItem>::iterator it = trackedBoxes.find(desktop);
43 if (it != trackedBoxes.end())
44 {
45 trackedBoxes.erase(it);
46 }
47 }
48
49
50 // TODO unify this later:
getLayoutPrefPath(Inkscape::UI::View::View * view)51 static Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view )
52 {
53 Glib::ustring prefPath;
54
55 if (reinterpret_cast<SPDesktop*>(view)->is_focusMode()) {
56 prefPath = "/focus/";
57 } else if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen()) {
58 prefPath = "/fullscreen/";
59 } else {
60 prefPath = "/window/";
61 }
62
63 return prefPath;
64 }
65
66 }
67
68 namespace Inkscape {
69 namespace UI {
70
71 UXManager* instance = nullptr;
72
73 class UXManagerImpl : public UXManager
74 {
75 public:
76 UXManagerImpl();
77 ~UXManagerImpl() override;
78
79 void addTrack( SPDesktopWidget* dtw ) override;
80 void delTrack( SPDesktopWidget* dtw ) override;
81
82 void connectToDesktop( std::vector<GtkWidget *> const & toolboxes, SPDesktop *desktop ) override;
83
84 gint getDefaultTask( SPDesktop *desktop ) override;
85 void setTask(SPDesktop* dt, gint val) override;
86
87 bool isWidescreen() const override;
88
89 private:
90 bool _widescreen;
91 };
92
getInstance()93 UXManager* UXManager::getInstance()
94 {
95 if (!instance) {
96 instance = new UXManagerImpl();
97 }
98 return instance;
99 }
100
101
102 UXManager::UXManager()
103 = default;
104
105 UXManager::~UXManager()
106 = default;
107
UXManagerImpl()108 UXManagerImpl::UXManagerImpl() :
109 _widescreen(false)
110 {
111 // Figure out if we're on a widescreen display
112 Gdk::Rectangle monitor_geometry = Inkscape::UI::get_monitor_geometry_primary();
113 int const width = monitor_geometry.get_width();
114 int const height = monitor_geometry.get_height();
115
116 if (width && height) {
117 gdouble aspect = static_cast<gdouble>(width) / static_cast<gdouble>(height);
118 if (aspect > 1.65) {
119 _widescreen = true;
120 }
121 }
122 }
123
124 UXManagerImpl::~UXManagerImpl()
125 = default;
126
isWidescreen() const127 bool UXManagerImpl::isWidescreen() const
128 {
129 return _widescreen;
130 }
131
getDefaultTask(SPDesktop * desktop)132 gint UXManagerImpl::getDefaultTask( SPDesktop *desktop )
133 {
134 gint taskNum = isWidescreen() ? 2 : 0;
135
136 Glib::ustring prefPath = getLayoutPrefPath( desktop );
137 taskNum = Inkscape::Preferences::get()->getInt( prefPath + "task/taskset", taskNum );
138 taskNum = (taskNum < 0) ? 0 : (taskNum > 2) ? 2 : taskNum;
139
140 return taskNum;
141 }
142
setTask(SPDesktop * dt,gint val)143 void UXManagerImpl::setTask(SPDesktop* dt, gint val)
144 {
145 for (auto dtw : dtws) {
146 gboolean notDone = Inkscape::Preferences::get()->getBool("/options/workarounds/dynamicnotdone", false);
147
148 if (dtw->desktop == dt) {
149 int taskNum = val;
150 switch (val) {
151 default:
152 case 0:
153 dtw->setToolboxPosition("ToolToolbar", GTK_POS_LEFT);
154 dtw->setToolboxPosition("CommandsToolbar", GTK_POS_TOP);
155 if (notDone) {
156 dtw->setToolboxPosition("AuxToolbar", GTK_POS_TOP);
157 }
158 dtw->setToolboxPosition("SnapToolbar", GTK_POS_RIGHT);
159 taskNum = val; // in case it was out of range
160 break;
161 case 1:
162 dtw->setToolboxPosition("ToolToolbar", GTK_POS_LEFT);
163 dtw->setToolboxPosition("CommandsToolbar", GTK_POS_TOP);
164 if (notDone) {
165 dtw->setToolboxPosition("AuxToolbar", GTK_POS_TOP);
166 }
167 dtw->setToolboxPosition("SnapToolbar", GTK_POS_TOP);
168 break;
169 case 2:
170 dtw->setToolboxPosition("ToolToolbar", GTK_POS_LEFT);
171 dtw->setToolboxPosition("CommandsToolbar", GTK_POS_RIGHT);
172 dtw->setToolboxPosition("SnapToolbar", GTK_POS_RIGHT);
173 if (notDone) {
174 dtw->setToolboxPosition("AuxToolbar", GTK_POS_RIGHT);
175 }
176 }
177 Glib::ustring prefPath = getLayoutPrefPath( dtw->desktop );
178 Inkscape::Preferences::get()->setInt( prefPath + "task/taskset", taskNum );
179 }
180 }
181 }
182
183
addTrack(SPDesktopWidget * dtw)184 void UXManagerImpl::addTrack( SPDesktopWidget* dtw )
185 {
186 if (std::find(dtws.begin(), dtws.end(), dtw) == dtws.end()) {
187 dtws.push_back(dtw);
188 }
189 }
190
delTrack(SPDesktopWidget * dtw)191 void UXManagerImpl::delTrack( SPDesktopWidget* dtw )
192 {
193 std::vector<SPDesktopWidget*>::iterator iter = std::find(dtws.begin(), dtws.end(), dtw);
194 if (iter != dtws.end()) {
195 dtws.erase(iter);
196 }
197 }
198
connectToDesktop(std::vector<GtkWidget * > const & toolboxes,SPDesktop * desktop)199 void UXManagerImpl::connectToDesktop( std::vector<GtkWidget *> const & toolboxes, SPDesktop *desktop )
200 {
201 if (!desktop)
202 {
203 return;
204 }
205 TrackItem &tracker = trackedBoxes[desktop];
206 std::vector<GtkWidget*>& tracked = tracker.boxes;
207 tracker.destroyConn = desktop->connectDestroy(&desktopDestructHandler);
208
209 for (auto toolbox : toolboxes) {
210 ToolboxFactory::setToolboxDesktop( toolbox, desktop );
211 if (find(tracked.begin(), tracked.end(), toolbox) == tracked.end()) {
212 tracked.push_back(toolbox);
213 }
214 }
215
216 if (std::find(desktops.begin(), desktops.end(), desktop) == desktops.end()) {
217 desktops.push_back(desktop);
218 }
219
220 gint taskNum = getDefaultTask( desktop );
221
222 // note: this will change once more options are in the task set support:
223 Inkscape::UI::UXManager::getInstance()->setTask( desktop, taskNum );
224 }
225
226
227 } // namespace UI
228 } // namespace Inkscape
229
230 /*
231 Local Variables:
232 mode:c++
233 c-file-style:"stroustrup"
234 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
235 indent-tabs-mode:nil
236 fill-column:99
237 End:
238 */
239 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
240