1 module pixelperfectengine.concrete.elements.menubar;
2 
3 public import pixelperfectengine.concrete.elements.base;
4 public import pixelperfectengine.concrete.popup;
5 
6 /**
7  * Implements a menubar, that is ideally contained under the top bar of the window,
8  * and contains a tree-like structure for menus.
9  */
10 public class MenuBar : WindowElement {
11 	private PopUpMenuElement[] menus;
12 	//private wstring[] menuNames;
13 	private int[] menuWidths;
14 	//private PopUpHandler popUpHandler;
15 	private int select, usedWidth;
16 	public EventDeleg onMenuEvent;
17 	/**
18 	 * Creates a menubar.
19 	 * Params:
20 	 *   source = The source of the emitted events.
21 	 *   position = The position, where the element should be drawn.
22 	 *   menus = The top level menus, which in turn contain any child menus present if any.
23 	 *   customStyle = A custom stylesheet if used.
24 	 */
25 	public this(string source, Box position, PopUpMenuElement[] menus, StyleSheet customStyle = null){
26 		this.customStyle = customStyle;
27 		this.source = source;
28 		this.position = position;
29 		//this.popUpHandler = popUpHandler;
30 		this.menus = menus;
31 		select = -1;
32 		menuWidths.length = menus.length + 1;
33 		menuWidths[0] = position.left;
34 		const int spacing = 2 * getStyleSheet().drawParameters["MenuBarHorizPadding"];
35 		for (size_t i ; i < menus.length ; i++) {
36 			menuWidths[i + 1] = menuWidths[i] + menus[i].text.getWidth + spacing;
37 		}
38 	}
39 	public override void draw() {
40 		StyleSheet ss = getStyleSheet();
41 		with (parent) {
42 			drawFilledBox(position, ss.getColor("window"));
43 			drawLine(position.cornerUL, position.cornerUR, ss.getColor("windowascent"));
44 			drawLine(position.cornerUL, position.cornerLL, ss.getColor("windowascent"));
45 			drawLine(position.cornerLL, position.cornerLR, ss.getColor("windowdescent"));
46 			drawLine(position.cornerUR, position.cornerLR, ss.getColor("windowdescent"));
47 		}
48 		if (select > -1) {
49 			parent.drawFilledBox(Box(menuWidths[select], position.top + 1, menuWidths[select + 1], position.bottom - 1), 
50 					ss.getColor("selection"));
51 		}
52 		foreach (size_t i, PopUpMenuElement menuItem ; menus) {
53 			parent.drawTextSL(Box(menuWidths[i], position.top, menuWidths[i+1], position.bottom), menuItem.text, Point(0,0));
54 		}
55 		if (onDraw !is null) {
56 			onDraw();
57 		}
58 	}
59 	private void redirectIncomingEvents(Event ev){
60 		if(onMenuEvent !is null){
61 			onMenuEvent(ev);
62 		}
63 	}
64 	///Passes mouse click event
65 	public override void passMCE(MouseEventCommons mec, MouseClickEvent mce) {
66 		if (state != ElementState.Enabled) return;
67 		if (mce.state) {
68 			for (int i ; i < menus.length ; i++) {
69 				if (menuWidths[i] < mce.x && menuWidths[i + 1] > mce.x) {
70 					select = i;
71 					draw;
72 					Coordinate c = parent.getAbsolutePosition(this);
73 					parent.addPopUpElement(new PopUpMenu(menus[i].getSubElements, source, &redirectIncomingEvents), c.left + 
74 							menuWidths[i], c.bottom);
75 					super.passMCE(mec, mce);
76 					return;
77 				}
78 			}
79 		}
80 		select = -1;
81 		super.passMCE(mec, mce);
82 	}
83 	///Passes mouse move event
84 	public override void passMME(MouseEventCommons mec, MouseMotionEvent mme) {
85 		if (position.isBetween(mme.x, mme.y)) {
86 			for (int i ; i < menus.length ; i++) {
87 				if (menuWidths[i] < mme.x && menuWidths[i + 1] > mme.x) {
88 					select = i;
89 					draw;
90 					return;
91 				}
92 			}
93 		}
94 		select = -1;
95 		draw;
96 		super.passMME(mec, mme);
97 	}
98 	///Called when an object loses focus.
99 	public override void focusTaken() {
100 		select = -1;
101 		super.focusTaken();
102 	}
103 }