1 /**
  2  * Creates a new ToolBarView.
  3  * 
  4  * @constructor
  5  */
  6 mindmaps.ToolBarView = function() {
  7 	var self = this;
  8 
  9 	this.init = function() {
 10 	};
 11 
 12 	/**
 13 	 * Adds a button to the toolbar with the given align function.
 14 	 * 
 15 	 * @param {mindmaps.ToolBarButton} button
 16 	 * @param {Function} alignFunc
 17 	 */
 18 	this.addButton = function(button, alignFunc) {
 19 		// var $button = this.createButton(button);
 20 		alignFunc(button.asJquery());
 21 	};
 22 
 23 	/**
 24 	 * Adds a set of buttons grouped together to the toolbar.
 25 	 * 
 26 	 * @param {mindmaps.ToolBarButton[]} buttons
 27 	 * @param {Function} alignFunc
 28 	 */
 29 	this.addButtonGroup = function(buttons, alignFunc) {
 30 		var $buttonset = $("<span/>");
 31 		buttons.forEach(function(button) {
 32 			// var $button = self.createButton(button);
 33 			$buttonset.append(button.asJquery());
 34 		});
 35 		$buttonset.buttonset();
 36 		alignFunc($buttonset);
 37 	};
 38 
 39 	/**
 40 	 * Adds a menu to the toolbar.
 41 	 * 
 42 	 * @param {mindmaps.ToolBarMenu} menu
 43 	 */
 44 	this.addMenu = function(menu) {
 45 		this.alignRight(menu.getContent());
 46 	};
 47 
 48 	/**
 49 	 * Adds the element to the left side of the toolbar.
 50 	 * 
 51 	 * @param {jQuery} $el
 52 	 */
 53 	this.alignLeft = function($el) {
 54 		$el.appendTo("#toolbar .buttons-left");
 55 	};
 56 
 57 	/**
 58 	 * Adds the element to the right side of the toolbar.
 59 	 * 
 60 	 * @param {jQuery} $el
 61 	 */
 62 	this.alignRight = function($el) {
 63 		$el.appendTo("#toolbar .buttons-right");
 64 	};
 65 };
 66 
 67 /**
 68  * Toolbar button model.
 69  * 
 70  * @constructor
 71  * @param {mindmaps.Command} command
 72  */
 73 
 74 mindmaps.ToolBarButton = function(command) {
 75 	this.command = command;
 76 
 77 	// callback to update display state
 78 	var self = this;
 79 	command.subscribe(mindmaps.Command.Event.ENABLED_CHANGED,
 80 			function(enabled) {
 81 				if (self.setEnabled) {
 82 					self.setEnabled(enabled);
 83 				}
 84 			});
 85 };
 86 
 87 /**
 88  * Returns whether the button should have an enabled style.
 89  * 
 90  * @returns {Boolean}
 91  */
 92 mindmaps.ToolBarButton.prototype.isEnabled = function() {
 93 	return this.command.enabled;
 94 };
 95 
 96 /**
 97  * Executes the button's command.
 98  */
 99 mindmaps.ToolBarButton.prototype.click = function() {
100 	this.command.execute();
101 };
102 
103 /**
104  * Gets the button's title.
105  * 
106  * @returns {String}
107  */
108 mindmaps.ToolBarButton.prototype.getTitle = function() {
109 	return this.command.label;
110 };
111 
112 /**
113  * Gets the tooltip.
114  * 
115  * @returns {String}
116  */
117 mindmaps.ToolBarButton.prototype.getToolTip = function() {
118 	var tooltip = this.command.description;
119 
120 	var shortcut = this.command.shortcut;
121 	if (shortcut) {
122 		tooltip += " [" + shortcut.toUpperCase() + "]";
123 	}
124 
125 	return tooltip;
126 };
127 
128 /**
129  * Gets the unique id of the button.
130  * 
131  * @returns {String}
132  */
133 mindmaps.ToolBarButton.prototype.getId = function() {
134 	return "button-" + this.command.id;
135 };
136 
137 /**
138  * Constructs a jQuery element that represents the button.
139  * 
140  * @returns {jQuery}
141  */
142 mindmaps.ToolBarButton.prototype.asJquery = function() {
143 	var self = this;
144 	var $button = $("<button/>", {
145 		id : this.getId(),
146 		title : this.getToolTip()
147 	}).click(function() {
148 		self.click();
149 	}).button({
150 		label : this.getTitle(),
151 		disabled : !this.isEnabled()
152 	});
153 
154 	var icon = this.command.icon;
155 	if (icon) {
156 		$button.button({
157 			icons : {
158 				primary : icon
159 			}
160 		});
161 	}
162 
163 	// callback to update display state
164 	this.setEnabled = function(enabled) {
165 		$button.button(enabled ? "enable" : "disable");
166 	};
167 
168 	return $button;
169 };
170 
171 /**
172  * Creates a new ToolBarMenu.
173  * 
174  * @constructor
175  * @param {String} title
176  * @param {String} icon
177  */
178 mindmaps.ToolBarMenu = function(title, icon) {
179 	var self = this;
180 	this.$menuWrapper = $("<span/>", {
181 		"class" : "menu-wrapper"
182 	});
183 
184 	this.$menuButton = $("<button/>").button({
185 		label : title,
186 		icons : {
187 			primary : icon,
188 			secondary : "ui-icon-triangle-1-s"
189 		}
190 	}).appendTo(this.$menuWrapper);
191 
192 	this.$menu = $("<div/>", {
193 		"class" : "menu"
194 	}).click(function() {
195 		/*
196 		 * hack to hide menu on click. visibility on hover is triggered by CSS.
197 		 * force display:none for a short time and remove class immediately
198 		 * again.
199 		 */
200 		self.$menu.addClass("hidden");
201 		setTimeout(function() {
202 			self.$menu.removeClass("hidden");
203 		}, 10);
204 	}).appendTo(this.$menuWrapper);
205 
206 	/**
207 	 * Adds a new button entry to the menu.
208 	 * 
209 	 * @param {mindmaps.ToolBarButton|mindmaps.ToolBarButtons[]} buttons a
210 	 *            single button or an array of buttons
211 	 */
212 	this.add = function(buttons) {
213 		if (!Array.isArray(buttons)) {
214 			buttons = [ buttons ];
215 		}
216 
217 		buttons.forEach(function(button) {
218 			var $button = button.asJquery().removeClass("ui-corner-all")
219 					.addClass("menu-item");
220 			this.$menu.append($button);
221 		}, this);
222 
223 		// last item gets rounded corners
224 		this.$menu.children().last().addClass("ui-corner-bottom").prev()
225 				.removeClass("ui-corner-bottom");
226 	};
227 
228 	/**
229 	 * Returns the underlying jquery object.
230 	 * 
231 	 * @returns {jQuery}
232 	 */
233 	this.getContent = function() {
234 		return this.$menuWrapper;
235 	};
236 };
237 
238 /**
239  * Creates a new ToolBarPresenter.
240  * 
241  * @constructor
242  * @param {mindmaps.EventBus} eventBus
243  * @param {mindmaps.CommandRegistry} commandRegistry
244  * @param {mindmaps.ToolBarView} view
245  * @param {mindmaps.MindMapModel} mindmapModel
246  */
247 mindmaps.ToolBarPresenter = function(eventBus, commandRegistry, view,
248 		mindmapModel) {
249 	/**
250 	 * Returns a button that registers with a command of the given commandType
251 	 * 
252 	 * @param {mindmaps.Command} commandType
253 	 * @returns {mindmaps.ToolBarButton}
254 	 */
255 	function commandToButton(commandType) {
256 		var command = commandRegistry.get(commandType);
257 		return new mindmaps.ToolBarButton(command);
258 	}
259 
260 	function commandsToButtons(commands) {
261 		return commands.map(commandToButton);
262 	}
263 
264 	// populate toolbar
265 
266 	// node buttons
267 	var nodeCommands = [ mindmaps.CreateNodeCommand, mindmaps.DeleteNodeCommand ];
268 	var nodeButtons = commandsToButtons(nodeCommands);
269 	view.addButtonGroup(nodeButtons, view.alignLeft);
270 
271 	// undo buttons
272 	var undoCommands = [ mindmaps.UndoCommand, mindmaps.RedoCommand ];
273 	var undoButtons = commandsToButtons(undoCommands);
274 	view.addButtonGroup(undoButtons, view.alignLeft);
275 
276 	// clipboard buttons.
277 	var clipboardCommands = [ mindmaps.CopyNodeCommand,
278 			mindmaps.CutNodeCommand, mindmaps.PasteNodeCommand ];
279 	var clipboardButtons = commandsToButtons(clipboardCommands);
280 	view.addButtonGroup(clipboardButtons, view.alignLeft);
281 
282 	// file menu
283 	var fileMenu = new mindmaps.ToolBarMenu("Mind map", "ui-icon-document");
284 	var fileCommands = [ mindmaps.NewDocumentCommand,
285 			mindmaps.OpenDocumentCommand, mindmaps.SaveDocumentCommand,
286 			mindmaps.CloseDocumentCommand ];
287 	var fileButtons = commandsToButtons(fileCommands);
288 	fileMenu.add(fileButtons);
289 	view.addMenu(fileMenu);
290 
291 	// help button
292 	view.addButton(commandToButton(mindmaps.HelpCommand), view.alignRight);
293 
294 	this.go = function() {
295 		view.init();
296 	};
297 };