1 /*
2  * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 #include <stdlib.h>
21 
22 #include <ZLApplication.h>
23 #include <ZLFile.h>
24 #include <ZLXMLReader.h>
25 #include <ZLResource.h>
26 #include <ZLibrary.h>
27 #include <ZLPopupData.h>
28 #include "ZLToolbar.h"
29 #include "ZLApplicationWindow.h"
30 
31 #include <optionEntries/ZLStringInfoEntry.h>
32 
33 class ZLToolbarCreator : public ZLXMLReader {
34 
35 public:
36 	ZLToolbarCreator(ZLToolbar &toolbar);
37 	void startElementHandler(const char *tag, const char **attributes);
38 
39 private:
40 	ZLToolbar &myToolbar;
41 };
42 
createToolbar(int index)43 void ZLApplication::createToolbar(int index) {
44 	toolbar(index);
45 	std::string fileName = ZLibrary::DefaultFilesPathPrefix();
46 	const bool isWindowToolbar = index == ZLApplicationWindow::WINDOW_TOOLBAR;
47 	fileName += isWindowToolbar ? "toolbar.xml" : "fullscreen_toolbar.xml";
48 	ZLToolbarCreator(isWindowToolbar ? *myToolbar : *myFullscreenToolbar).readDocument(ZLFile(fileName));
49 }
50 
toolbar(int index) const51 const ZLToolbar &ZLApplication::toolbar(int index) const {
52 	if (index == ZLApplicationWindow::WINDOW_TOOLBAR) {
53 		if (myToolbar.isNull()) {
54 			myToolbar = new ZLToolbar();
55 		}
56 		return *myToolbar;
57 	} else {
58 		if (myFullscreenToolbar.isNull()) {
59 			myFullscreenToolbar = new ZLToolbar();
60 		}
61 		return *myFullscreenToolbar;
62 	}
63 }
64 
registerPopupData(const std::string & actionId,shared_ptr<ZLPopupData> popupData)65 void ZLApplication::registerPopupData(const std::string &actionId, shared_ptr<ZLPopupData> popupData) {
66 	toolbar(ZLApplicationWindow::WINDOW_TOOLBAR);
67 	myToolbar->registerPopupData(actionId, popupData);
68 }
69 
registerPopupData(const std::string & actionId,shared_ptr<ZLPopupData> popupData)70 void ZLToolbar::registerPopupData(const std::string &actionId, shared_ptr<ZLPopupData> popupData) {
71 	myPopupDataMap[actionId] = popupData;
72 }
73 
ZLToolbarCreator(ZLToolbar & toolbar)74 ZLToolbarCreator::ZLToolbarCreator(ZLToolbar &toolbar) : myToolbar(toolbar) {
75 }
76 
startElementHandler(const char * tag,const char ** attributes)77 void ZLToolbarCreator::startElementHandler(const char *tag, const char **attributes) {
78 	static const std::string BUTTON = "button";
79 	static const std::string MENU_BUTTON = "menuButton";
80 	static const std::string TOGGLE_BUTTON = "toggleButton";
81 	static const std::string TEXT_FIELD = "textField";
82 	static const std::string COMBO_BOX = "comboBox";
83 	static const std::string SEARCH_FIELD = "searchField";
84 	static const std::string SEPARATOR = "separator";
85 	static const std::string FILL_SEPARATOR = "fillSeparator";
86 
87 	const char *id = attributeValue(attributes, "id");
88 
89 	if (SEPARATOR == tag) {
90 		new ZLToolbar::SeparatorItem(myToolbar, ZLToolbar::Item::SEPARATOR);
91 	} else if (FILL_SEPARATOR == tag) {
92 		new ZLToolbar::SeparatorItem(myToolbar, ZLToolbar::Item::FILL_SEPARATOR);
93 	} else if (id == 0) {
94 		return;
95 	} else if (BUTTON == tag) {
96 		new ZLToolbar::PlainButtonItem(myToolbar, id);
97 	} else if (MENU_BUTTON == tag) {
98 		new ZLToolbar::MenuButtonItem(myToolbar, id);
99 	} else if (TOGGLE_BUTTON == tag) {
100 		const char *groupId = attributeValue(attributes, "group");
101 		const char *isDefault = attributeValue(attributes, "default");
102 		if (groupId != 0) {
103 			ZLToolbar::ButtonGroup &group = myToolbar.getButtonGroup(groupId);
104 			ZLToolbar::ToggleButtonItem *button = new ZLToolbar::ToggleButtonItem(myToolbar, id, group);
105 			if (isDefault != 0) {
106 				group.setDefaultAction(id);
107 			}
108 			if (group.defaultAction() == id) {
109 				button->press();
110 			}
111 		}
112 	} else if (TEXT_FIELD == tag || COMBO_BOX == tag || SEARCH_FIELD == tag) {
113 		const char *parameterId = attributeValue(attributes, "parameterId");
114 		const char *maxWidth = attributeValue(attributes, "maxWidth");
115 		if (parameterId != 0 && maxWidth != 0) {
116 			int nMaxWidth = atoi(maxWidth);
117 			if (nMaxWidth > 0) {
118 				ZLToolbar::Item::Type type = ZLToolbar::Item::TEXT_FIELD;
119 				if (COMBO_BOX == tag) {
120 					type = ZLToolbar::Item::COMBO_BOX;
121 				} else if (SEARCH_FIELD == tag) {
122 					type = ZLToolbar::Item::SEARCH_FIELD;
123 				}
124 				ZLToolbar::ParameterItem *item = new ZLToolbar::ParameterItem(
125 					myToolbar, type, id, parameterId, nMaxWidth
126 				);
127 				const char *symbolSet = attributeValue(attributes, "symbols");
128 				if (symbolSet != 0 && std::string(symbolSet) == "digits") {
129 					item->setSymbolSet(ZLToolbar::ParameterItem::SET_DIGITS);
130 				}
131 			}
132 		}
133 	}
134 }
135 
items() const136 const ZLToolbar::ItemVector &ZLToolbar::items() const {
137 	return myItems;
138 }
139 
resource(const std::string & id)140 const ZLResource &ZLToolbar::resource(const std::string &id) {
141 	return ZLResource::resource("toolbar")[id];
142 }
143 
Item(ZLToolbar & toolbar,Type type)144 ZLToolbar::Item::Item(ZLToolbar &toolbar, Type type) : myToolbar(toolbar), myType(type) {
145 	toolbar.myItems.push_back(this);
146 }
147 
~Item()148 ZLToolbar::Item::~Item() {
149 }
150 
toolbar() const151 const ZLToolbar &ZLToolbar::Item::toolbar() const {
152 	return myToolbar;
153 }
154 
type() const155 ZLToolbar::Item::Type ZLToolbar::Item::type() const {
156 	return myType;
157 }
158 
ActionItem(ZLToolbar & toolbar,Type type,const std::string & actionId)159 ZLToolbar::ActionItem::ActionItem(ZLToolbar &toolbar, Type type, const std::string &actionId) :
160 	Item(toolbar, type), myActionId(actionId), myResource(toolbar.resource(actionId)) {
161 }
162 
actionId() const163 const std::string &ZLToolbar::ActionItem::actionId() const {
164 	return myActionId;
165 }
166 
label() const167 const std::string &ZLToolbar::ActionItem::label() const {
168 	const ZLResource &labelResource = myResource["label"];
169 	if (!labelResource.hasValue()) {
170 		static const std::string EMPTY;
171 		return EMPTY;
172 	}
173 	return labelResource.value();
174 }
175 
tooltip() const176 const std::string &ZLToolbar::ActionItem::tooltip() const {
177 	const ZLResource &tooltipResource = myResource["tooltip"];
178 	if (!tooltipResource.hasValue()) {
179 		static const std::string EMPTY;
180 		return EMPTY;
181 	}
182 	return tooltipResource.value();
183 }
184 
AbstractButtonItem(ZLToolbar & toolbar,Type type,const std::string & actionId)185 ZLToolbar::AbstractButtonItem::AbstractButtonItem(ZLToolbar &toolbar, Type type, const std::string &actionId) : ActionItem(toolbar, type, actionId) {
186 }
187 
PlainButtonItem(ZLToolbar & toolbar,const std::string & actionId)188 ZLToolbar::PlainButtonItem::PlainButtonItem(ZLToolbar &toolbar, const std::string &actionId) :
189 	AbstractButtonItem(toolbar, PLAIN_BUTTON, actionId) {
190 }
191 
MenuButtonItem(ZLToolbar & toolbar,const std::string & actionId)192 ZLToolbar::MenuButtonItem::MenuButtonItem(ZLToolbar &toolbar, const std::string &actionId) :
193 	AbstractButtonItem(toolbar, MENU_BUTTON, actionId) {
194 }
195 
popupTooltip() const196 const std::string &ZLToolbar::MenuButtonItem::popupTooltip() const {
197 	const ZLResource &popupResource = myResource["popup"];
198 	if (!popupResource.hasValue()) {
199 		static const std::string EMPTY;
200 		return EMPTY;
201 	}
202 	return popupResource.value();
203 }
204 
popupData() const205 shared_ptr<ZLPopupData> ZLToolbar::MenuButtonItem::popupData() const {
206 	std::map<std::string,shared_ptr<ZLPopupData> >::const_iterator it =
207 		toolbar().myPopupDataMap.find(actionId());
208 	return (it == toolbar().myPopupDataMap.end()) ? 0 : it->second;
209 }
210 
ToggleButtonItem(ZLToolbar & toolbar,const std::string & actionId,ButtonGroup & group)211 ZLToolbar::ToggleButtonItem::ToggleButtonItem(ZLToolbar &toolbar, const std::string &actionId, ButtonGroup &group) : AbstractButtonItem(toolbar, TOGGLE_BUTTON, actionId), myGroup(group) {
212 	myGroup.myItems.insert(this);
213 }
214 
iconName() const215 const std::string &ZLToolbar::AbstractButtonItem::iconName() const {
216 	return actionId();
217 }
218 
buttonGroup()219 ZLToolbar::ButtonGroup &ZLToolbar::ToggleButtonItem::buttonGroup() {
220 	return myGroup;
221 }
222 
press()223 void ZLToolbar::ToggleButtonItem::press() {
224 	myGroup.press(this);
225 }
226 
isPressed() const227 bool ZLToolbar::ToggleButtonItem::isPressed() const {
228 	return this == myGroup.myPressedItem;
229 }
230 
getButtonGroup(const std::string & id)231 ZLToolbar::ButtonGroup &ZLToolbar::getButtonGroup(const std::string &id) {
232 	shared_ptr<ButtonGroup> group = myButtonGroups[id];
233 	if (group.isNull()) {
234 		group = new ButtonGroup(id);
235 		myButtonGroups[id] = group;
236 	}
237 	return *group;
238 }
239 
ZLToolbar()240 ZLToolbar::ZLToolbar() {
241 }
242 
ButtonGroup(const std::string & groupId)243 ZLToolbar::ButtonGroup::ButtonGroup(const std::string &groupId) : myPressedItem(0), myDefaultButtonOption(ZLCategoryKey::LOOK_AND_FEEL, "ToggleButtonGroup", groupId, "") {
244 }
245 
press(const ToggleButtonItem * item)246 void ZLToolbar::ButtonGroup::press(const ToggleButtonItem *item) {
247 	myPressedItem = item;
248 	myDefaultButtonOption.setValue(item->actionId());
249 }
250 
setDefaultAction(const std::string & actionId)251 void ZLToolbar::ButtonGroup::setDefaultAction(const std::string &actionId) {
252 	if (myDefaultButtonOption.value().empty()) {
253 		myDefaultButtonOption.setValue(actionId);
254 	}
255 }
256 
defaultAction() const257 const std::string &ZLToolbar::ButtonGroup::defaultAction() const {
258 	return myDefaultButtonOption.value();
259 }
260 
SeparatorItem(ZLToolbar & toolbar,Type type)261 ZLToolbar::SeparatorItem::SeparatorItem(ZLToolbar &toolbar, Type type) : Item(toolbar, type) {
262 }
263 
ParameterItem(ZLToolbar & toolbar,Type type,const std::string & actionId,const std::string & parameterId,int maxWidth)264 ZLToolbar::ParameterItem::ParameterItem(ZLToolbar &toolbar, Type type, const std::string &actionId, const std::string &parameterId, int maxWidth) :
265 	ActionItem(toolbar, type, actionId),
266 	myParameterId(parameterId),
267 	myMaxWidth(maxWidth),
268 	mySymbolSet(SET_ANY) {
269 }
270 
parameterId() const271 const std::string &ZLToolbar::ParameterItem::parameterId() const {
272 	return myParameterId;
273 }
274 
maxWidth() const275 int ZLToolbar::ParameterItem::maxWidth() const {
276 	return myMaxWidth;
277 }
278 
symbolSet() const279 ZLToolbar::ParameterItem::SymbolSet ZLToolbar::ParameterItem::symbolSet() const {
280 	return mySymbolSet;
281 }
282 
setSymbolSet(SymbolSet symbolSet)283 void ZLToolbar::ParameterItem::setSymbolSet(SymbolSet symbolSet) {
284 	mySymbolSet = symbolSet;
285 }
286 
resource(const std::string & actionId)287 const ZLResource &ZLPopupData::resource(const std::string &actionId) {
288 	return ZLToolbar::resource(actionId);
289 }
290