]> git.lyx.org Git - lyx.git/blob - src/frontends/Toolbars.cpp
Final fix to get unit with optional arg (value) working
[lyx.git] / src / frontends / Toolbars.cpp
1 /**
2  * \file Toolbars.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Angus Leeming
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "frontends/Toolbars.h"
15
16 #include "frontends/LyXView.h"
17
18 #include "Buffer.h"
19 #include "BufferParams.h"
20 #include "debug.h"
21 #include "FuncRequest.h"
22 #include "FuncStatus.h"
23 #include "gettext.h"
24 #include "Layout.h"
25 #include "LyX.h"
26 #include "LyXFunc.h"
27 #include "TextClass.h"
28
29
30 using std::endl;
31 using std::string;
32
33 namespace lyx {
34 namespace frontend {
35
36 Toolbars::Toolbars(LyXView & owner)
37         : owner_(owner),
38           layout_(0),
39           last_textclass_(TextClassPtr())
40 {}
41
42 #define TurnOnFlag(x)   flags |= ToolbarInfo::x
43 #define TurnOffFlag(x)  flags &= ~ToolbarInfo::x
44
45 void Toolbars::initFlags(ToolbarInfo & tbinfo)
46 {
47         ToolbarSection::ToolbarInfo & info = LyX::ref().session().toolbars().load(tbinfo.name);
48
49         unsigned int flags = static_cast<unsigned int>(tbinfo.flags);
50
51         // Remove default.ui positions. Only when a valid postion is stored
52         // in the session file the default.ui value will be overwritten
53         unsigned int save = flags;
54         TurnOffFlag(TOP);
55         TurnOffFlag(BOTTOM);
56         TurnOffFlag(RIGHT);
57         TurnOffFlag(LEFT);
58
59         bool valid_location = true;
60         // init tbinfo.flags with saved location
61         if (info.location == ToolbarSection::ToolbarInfo::TOP)
62                 TurnOnFlag(TOP);
63         else if (info.location == ToolbarSection::ToolbarInfo::BOTTOM)
64                 TurnOnFlag(BOTTOM);
65         else if (info.location == ToolbarSection::ToolbarInfo::RIGHT)
66                 TurnOnFlag(RIGHT);
67         else if (info.location == ToolbarSection::ToolbarInfo::LEFT)
68                 TurnOnFlag(LEFT);
69         else {
70                 // use setting from default.ui
71                 flags = save;
72                 valid_location = false;
73         }
74
75         // invalid location is for a new toolbar that has no saved information,
76         // so info.visible is not used for this case.
77         if (valid_location) {
78                 // init tbinfo.flags with saved visibility,
79                 TurnOffFlag(ON);
80                 TurnOffFlag(OFF);
81                 TurnOffFlag(AUTO);
82                 if (info.state == ToolbarSection::ToolbarInfo::ON)
83                         TurnOnFlag(ON);
84                 else if (info.state == ToolbarSection::ToolbarInfo::OFF)
85                         TurnOnFlag(OFF);
86                 else
87                         TurnOnFlag(AUTO);
88         }
89         /*
90         std::cout << "State " << info.state << " FLAGS: " << flags
91                 << " ON:" << (flags & ToolbarBackend::ON)
92                 << " OFF:" << (flags & ToolbarBackend::OFF)
93                 << " L:" << (flags & ToolbarBackend::LEFT)
94                 << " R:" << (flags & ToolbarBackend::RIGHT)
95                 << " T:" << (flags & ToolbarBackend::TOP)
96                 << " B:" << (flags & ToolbarBackend::BOTTOM)
97                 << " MA:" << (flags & ToolbarBackend::MATH)
98                 << " RE:" << (flags & ToolbarBackend::REVIEW)
99                 << " TB:" << (flags & ToolbarBackend::TABLE)
100                 << " AU:" << (flags & ToolbarBackend::AUTO)
101                 << std::endl;
102         */
103         // now set the flags
104         tbinfo.flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
105 }
106
107
108 void Toolbars::init()
109 {
110         // extracts the toolbars from the backend
111         ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
112         ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
113
114         // init flags will also add these toolbars to session if they
115         // are not already there (e.g. first run of lyx).
116         for (; cit != end; ++cit)
117                 initFlags(*cit);
118
119         // add toolbars according the order in session
120         ToolbarSection::ToolbarList::const_iterator tb = LyX::ref().session().toolbars().begin();
121         ToolbarSection::ToolbarList::const_iterator te = LyX::ref().session().toolbars().end();
122         ToolbarSection::ToolbarInfo::Location last_loc = ToolbarSection::ToolbarInfo::NOTSET;
123         int last_posx = 0;
124         int last_posy = 0;
125         for (; tb != te; ++tb) {
126                 LYXERR(Debug::INIT) << "Adding " << tb->get<0>() << " at position " << tb->get<1>().posx << " " << tb->get<1>().posy << endl;
127                 // add toolbar break if posx or posy changes
128                 bool newline = tb->get<1>().location == last_loc && (
129                         // if two toolbars at the same location, assume uninitialized and add toolbar break
130                         (tb->get<1>().posx == last_posx && tb->get<1>().posy == last_posy) ||
131                         (last_loc == ToolbarSection::ToolbarInfo::TOP && tb->get<1>().posy != last_posy) ||
132                         (last_loc == ToolbarSection::ToolbarInfo::BOTTOM && tb->get<1>().posy != last_posy) ||
133                         (last_loc == ToolbarSection::ToolbarInfo::LEFT && tb->get<1>().posx != last_posx) ||
134                         (last_loc == ToolbarSection::ToolbarInfo::RIGHT && tb->get<1>().posx != last_posx) );
135                 // find the backend item and add
136                 for (cit = toolbarbackend.begin(); cit != end; ++cit)
137                         if (cit->name == tb->get<0>()) {
138                                 add(*cit, newline);
139                                 last_loc = tb->get<1>().location;
140                                 last_posx = tb->get<1>().posx;
141                                 last_posy = tb->get<1>().posy;
142                                 break;
143                         }
144         }
145 }
146
147
148 Toolbar * Toolbars::display(string const & name, bool show)
149 {
150         ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
151         ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
152
153         for (; cit != end; ++cit) {
154                 if (cit->name == name) {
155                         unsigned int flags = cit->flags;
156                         TurnOffFlag(ON);
157                         TurnOffFlag(OFF);
158                         TurnOffFlag(AUTO);
159                         if (show)
160                                 TurnOnFlag(ON);
161                         else
162                                 TurnOnFlag(OFF);
163                         cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
164                         return displayToolbar(*cit, show);
165                 }
166         }
167
168         LYXERR(Debug::GUI) << "Toolbar::display: no toolbar named "
169                 << name << endl;
170         return 0;
171 }
172
173
174 ToolbarInfo * Toolbars::getToolbarInfo(string const & name)
175 {
176         return toolbarbackend.getUsedToolbarInfo(name);
177 }
178
179
180 void Toolbars::toggleToolbarState(string const & name, bool allowauto)
181 {
182         ToolbarInfo * tbi = toolbarbackend.getUsedToolbarInfo(name);
183
184         if (!tbi) {
185                 LYXERR(Debug::GUI) << "Toolbar::display: no toolbar named "
186                         << name << endl;
187                 return;
188         }
189
190         int flags = tbi->flags;
191         // off -> on
192         if (flags & ToolbarInfo::OFF) {
193                 TurnOffFlag(OFF);
194                 TurnOnFlag(ON);
195         // auto -> off
196         } else if (flags & ToolbarInfo::AUTO) {
197                 TurnOffFlag(AUTO);
198                 TurnOnFlag(OFF);
199         } else if (allowauto 
200                    && ((flags & ToolbarInfo::MATH) 
201                        || (flags & ToolbarInfo::TABLE)
202                        || (flags & ToolbarInfo::REVIEW))) {
203                 // for math etc, toggle from on -> auto
204                 TurnOffFlag(ON);
205                 TurnOnFlag(AUTO);
206         } else {
207                 // for others, toggle from on -> off
208                 TurnOffFlag(ON);
209                 TurnOnFlag(OFF);
210         }
211         tbi->flags = static_cast<ToolbarInfo::Flags>(flags);
212 }
213 #undef TurnOnFlag
214 #undef TurnOffFlag
215
216
217 void Toolbars::update(bool in_math, bool in_table, bool review)
218 {
219         update();
220
221         // extracts the toolbars from the backend
222         ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
223         ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
224
225         for (; cit != end; ++cit) {
226                 if (cit->flags & ToolbarInfo::ON)
227                         displayToolbar(*cit, true);
228                 else if (cit->flags & ToolbarInfo::OFF)
229                         displayToolbar(*cit, false);
230                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::MATH))
231                         displayToolbar(*cit, in_math);
232                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::TABLE))
233                         displayToolbar(*cit, in_table);
234                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::REVIEW))
235                         displayToolbar(*cit, review);
236         }
237 }
238
239
240 bool Toolbars::visible(string const & name) const
241 {
242         std::map<string, ToolbarPtr>::const_iterator it =
243                 toolbars_.find(name);
244         if (it == toolbars_.end())
245                 return false;
246         return it->second.get()->isVisible();
247 }
248
249
250 void Toolbars::saveToolbarInfo()
251 {
252         ToolbarSection & tb = LyX::ref().session().toolbars();
253
254         for (ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
255                 cit != toolbarbackend.end(); ++cit) {
256                 ToolbarsMap::iterator it = toolbars_.find(cit->name);
257                 BOOST_ASSERT(it != toolbars_.end());
258                 // get toolbar info from session.
259                 ToolbarSection::ToolbarInfo & info = tb.load(cit->name);
260                 if (cit->flags & ToolbarInfo::ON)
261                         info.state = ToolbarSection::ToolbarInfo::ON;
262                 else if (cit->flags & ToolbarInfo::OFF)
263                         info.state = ToolbarSection::ToolbarInfo::OFF;
264                 else if (cit->flags & ToolbarInfo::AUTO)
265                         info.state = ToolbarSection::ToolbarInfo::AUTO;
266                 // save other information
267                 // if auto, frontend should *not* set on/off
268                 it->second->saveInfo(info);
269                 // maybe it is useful to update flags with real status. I do not know
270                 /*
271                 if (!(cit->flags & ToolbarInfo::AUTO)) {
272                         unsigned int flags = static_cast<unsigned int>(cit->flags);
273                         flags &= ~(info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::OFF : ToolbarInfo::ON);
274                         flags |= (info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::ON : ToolbarInfo::OFF);
275                         if (info.state == ToolbarSection::ToolbarInfo::ON)
276                         cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
277                 }
278                 */
279         }
280 }
281
282
283 void Toolbars::setLayout(docstring const & layout)
284 {
285         if (layout_)
286                 layout_->set(layout);
287 }
288
289
290 bool Toolbars::updateLayoutList(TextClassPtr textclass)
291 {
292         // update the layout display
293         if (last_textclass_ != textclass) {
294                 if (layout_)
295                         layout_->update();
296                 last_textclass_ = textclass;
297                 return true;
298         } else
299                 return false;
300 }
301
302
303 void Toolbars::openLayoutList()
304 {
305         if (layout_)
306                 layout_->open();
307 }
308
309
310 void Toolbars::clearLayoutList()
311 {
312         last_textclass_ = TextClassPtr();
313         if (layout_)
314                 layout_->clear();
315 }
316
317
318 void Toolbars::add(ToolbarInfo const & tbinfo, bool newline)
319 {
320         ToolbarPtr tb_ptr(owner_.makeToolbar(tbinfo, newline));
321         toolbars_[tbinfo.name] = tb_ptr;
322
323         if (tbinfo.flags & ToolbarInfo::ON)
324                 tb_ptr->show(false);
325         else
326                 tb_ptr->hide(false);
327
328         if (tb_ptr->layout())
329                 layout_ = tb_ptr->layout();
330 }
331
332
333 Toolbar * Toolbars::displayToolbar(ToolbarInfo const & tbinfo,
334                               bool show_it)
335 {
336         ToolbarsMap::iterator it = toolbars_.find(tbinfo.name);
337         BOOST_ASSERT(it != toolbars_.end());
338
339         if (show_it)
340                 it->second->show(true);
341         else
342                 it->second->hide(true);
343
344         return it->second.get();
345 }
346
347
348 void Toolbars::update()
349 {
350         ToolbarsMap::const_iterator it = toolbars_.begin();
351         ToolbarsMap::const_iterator const end = toolbars_.end();
352         for (; it != end; ++it)
353                 it->second->update();
354
355         bool const enable =
356                 lyx::getStatus(FuncRequest(LFUN_LAYOUT)).enabled();
357
358         if (layout_)
359                 layout_->setEnabled(enable);
360 }
361
362
363 void layoutSelected(LyXView & lv, docstring const & name)
364 {
365         TextClass const & tc = lv.buffer()->params().getTextClass();
366
367         TextClass::const_iterator it  = tc.begin();
368         TextClass::const_iterator const end = tc.end();
369         for (; it != end; ++it) {
370                 docstring const & itname = (*it)->name();
371                 if (translateIfPossible(itname) == name) {
372                         FuncRequest const func(LFUN_LAYOUT, itname,
373                                                FuncRequest::TOOLBAR);
374                         lv.dispatch(func);
375                         return;
376                 }
377         }
378         lyxerr << "ERROR (layoutSelected): layout not found!"
379                << endl;
380 }
381
382 } // namespace frontend
383 } // namespace lyx