1 module PixelPerfectEngine.concrete.popup.popupmenu; 2 3 import PixelPerfectEngine.concrete.popup.base; 4 5 /** 6 * To create drop-down lists, menu bars, etc. 7 */ 8 public class PopUpMenu : PopUpElement { 9 //private wstring[] texts; 10 //private string[] sources; 11 12 //private uint[int] hotkeyCodes; 13 //protected Bitmap8Bit[int] icons; 14 protected int width, height, select; 15 PopUpMenuElement[] elements; 16 public EventDeleg onMenuSelect; 17 /** 18 * Creates a single PopUpMenu. 19 */ 20 public this(PopUpMenuElement[] elements, string source, EventDeleg onMenuSelect){ 21 this.elements = elements; 22 this.source = source; 23 //this. iconWidth = iconWidth; 24 select = -1; 25 this.onMenuSelect = onMenuSelect; 26 } 27 public override void draw(){ 28 StyleSheet ss = getStyleSheet(); 29 if(output is null){ 30 31 //minwidth = (ss.drawParameters["PopUpMenuVertPadding"] * 2); 32 //int width; 33 foreach(e; elements){ 34 int newwidth = e.text.getWidth();// + (e is null) ? 0 : e.secondaryText.getWidth(); 35 if(e.secondaryText !is null) newwidth += e.secondaryText.getWidth() + ss.drawParameters["PopUpMenuMinTextSpace"]; 36 //assert(newwidth); 37 //writeln(e.text.getWidth()); 38 if(newwidth > width){ 39 width = newwidth; 40 //writeln(width); 41 } 42 height += e.text.font.size + (ss.drawParameters["PopUpMenuVertPadding"] * 2); 43 } 44 width += (ss.drawParameters["PopUpMenuHorizPadding"] * 2); 45 height += ss.drawParameters["PopUpMenuVertPadding"] * 2; 46 position = Box(0, 0, width - 1, height - 1); 47 output = new BitmapDrawer(width, height); 48 } 49 Box position0 = Box(0, 0, width - 1, height - 1); 50 output.drawFilledBox(position0, ss.getColor("window"));//output.drawFilledRectangle(0,width - 1,0,height - 1,ss.getColor("window")); 51 52 if(select > -1){ 53 int y0 = cast(int)((height / elements.length) * select); 54 int y1 = cast(int)((height / elements.length) + y0); 55 output.drawFilledBox(Box(1, y0 + 1, position0.width, y1 + 1), ss.getColor("selection")); //output.drawFilledRectangle(1, width - 1, y0 + 1, y1 + 1, ss.getColor("selection")); 56 } 57 58 59 int y = 1 + ss.drawParameters["PopUpMenuVertPadding"]; 60 foreach(e; elements){ 61 if(e.secondaryText !is null){ 62 /+output.drawColorText(width - ss.drawParameters["PopUpMenuHorizPadding"] - 1, y, e.secondaryText, 63 ss.getFontset("default"), ss.getColor("PopUpMenuSecondaryTextColor"), FontFormat.RightJustified);+/ 64 //const int textLength = e.secondaryText.getWidth; 65 const Box textPos = Box(ss.drawParameters["PopUpMenuHorizPadding"], y, 66 position0.width - ss.drawParameters["PopUpMenuHorizPadding"], y + e.secondaryText.font.size); 67 output.drawSingleLineText(textPos, e.secondaryText); 68 } 69 /+output.drawColorText(ss.drawParameters["PopUpMenuHorizPadding"] + iconWidth, y, e.text, ss.getFontset("default"), 70 ss.getColor("normaltext"), 0);+/ 71 //const int textLength = e.text.getWidth; 72 const Box textPos = Box(ss.drawParameters["PopUpMenuHorizPadding"], y, 73 position0.width - ss.drawParameters["PopUpMenuHorizPadding"], y + e.text.font.size); 74 output.drawSingleLineText(textPos, e.text); 75 /+if(e.getIcon() !is null){ 76 //output.insertBitmap(ss.drawParameters["PopUpMenuHorizPadding"], y, e.getIcon()); 77 }+/ 78 y += e.text.font.size + (ss.drawParameters["PopUpMenuVertPadding"] * 2); 79 } 80 81 //output.drawRectangle(1,1,height-1,width-1,ss.getColor("windowascent")); 82 /+output.drawLine(0,0,0,height-1,ss.getColor("windowascent")); 83 output.drawLine(0,width-1,0,0,ss.getColor("windowascent")); 84 output.drawLine(0,width-1,height-1,height-1,ss.getColor("windowdescent")); 85 output.drawLine(width-1,width-1,0,height-1,ss.getColor("windowdescent"));+/ 86 with (output) { 87 drawLine(position0.cornerUL, position0.cornerUR, ss.getColor("windowascent")); 88 drawLine(position0.cornerUL, position0.cornerLL, ss.getColor("windowascent")); 89 drawLine(position0.cornerLL, position0.cornerLR, ss.getColor("windowdescent")); 90 drawLine(position0.cornerUR, position0.cornerLR, ss.getColor("windowdescent")); 91 } 92 if(onDraw !is null){ 93 onDraw(); 94 } 95 } 96 public override void passMCE(MouseEventCommons mec, MouseClickEvent mce) { 97 if (mce.state) { 98 mce.y -= position.top; 99 mce.y /= height / elements.length; 100 if(elements[mce.y].source == "\\submenu\\"){ 101 PopUpMenu m = new PopUpMenu(elements[mce.y].subElements, this.source, onMenuSelect); 102 m.onMouseClick = onMouseClick; 103 //parent.getAbsolutePosition() 104 parent.addPopUpElement(m, position.left + width, position.top + mce.y * cast(int)(height / elements.length)); 105 //parent.closePopUp(this); 106 }else{ 107 //invokeActionEvent(new Event(elements[offsetY].source, source, null, null, null, offsetY, EventType.CLICK)); 108 if(onMenuSelect !is null) 109 onMenuSelect(new MenuEvent(this, SourceType.PopUpElement, elements[mce.y].text, mce.y, elements[mce.y].source)); 110 parent.endPopUpSession(this); 111 //parent.closePopUp(this); 112 } 113 } 114 115 } 116 public override void passMME(MouseEventCommons mec, MouseMotionEvent mme) { 117 if(!position.isBetween(mme.x, mme.y)){ 118 if(select != -1){ 119 select = -1; 120 draw; 121 } 122 }else{ 123 mme.y -= position.top; 124 mme.y /= height / elements.length; 125 if(mme.y < elements.length){ 126 select = mme.y; 127 } 128 draw(); 129 } 130 } 131 132 } 133 /** 134 * Defines a single MenuElement, also can contain multiple subelements. 135 */ 136 public class PopUpMenuElement { 137 public string source; 138 public Text text, secondaryText; 139 //protected Bitmap8Bit icon; 140 private PopUpMenuElement[] subElements; 141 private ushort keymod; 142 private int keycode; 143 public int iconWidth; 144 145 /** 146 * Generates a menu element with the supplied parameters. 147 * Uses the default formatting to initialize texts. 148 */ 149 public this(string source, dstring text, dstring secondaryText = "", PopUpMenuElement[] subElements = null) { 150 StyleSheet ss = globalDefaultStyle; 151 Text st; 152 if (secondaryText.length) { 153 st = new Text(secondaryText, ss.getChrFormatting("popUpMenuSecondary")); 154 } 155 this(source, new Text(text, ss.getChrFormatting("popUpMenu")), st, subElements); 156 } 157 /** 158 * Generates a menu element with the supplied parameters. 159 * Text formatting can be supplied with the objects. 160 */ 161 public this(string source, Text text, Text secondaryText = null, PopUpMenuElement[] subElements = []) { 162 this.source = source; 163 this.text = text; 164 this.secondaryText = secondaryText; 165 this.subElements = subElements; 166 } 167 ///DEPRECATED! 168 ///REMOVE BY VER 0.11! 169 public Bitmap8Bit getIcon(){ 170 return text.icon; 171 } 172 ///DEPRECATED! 173 ///REMOVE BY VER 0.11! 174 public void setIcon(Bitmap8Bit icon){ 175 text.icon = icon; 176 } 177 ///Returns all subelements of this menu element. 178 public PopUpMenuElement[] getSubElements() { 179 return subElements; 180 } 181 /** 182 * Assigns this current object's all subelements at once. 183 */ 184 public void loadSubElements(PopUpMenuElement[] e){ 185 subElements = e; 186 } 187 /** 188 * Gets the subelement at the given index. 189 */ 190 public PopUpMenuElement opIndex(size_t i){ 191 return subElements[i]; 192 } 193 /** 194 * Sets the subelement at the given index. 195 */ 196 public PopUpMenuElement opIndexAssign(PopUpMenuElement value, size_t i){ 197 subElements[i] = value; 198 return value; 199 } 200 /** 201 * Implements appending to the last position of the underlying array. 202 */ 203 public PopUpMenuElement opOpAssign(string op)(PopUpMenuElement value){ 204 static if(op == "~"){ 205 subElements ~= value; 206 return value; 207 }else static assert("Operator " ~ op ~ " not supported!"); 208 } 209 ///Returns the lenght of the underlying array. 210 public size_t getLength(){ 211 return subElements.length; 212 } 213 ///Sets the lenght of the underlying array. 214 public void setLength(int l){ 215 subElements.length = l; 216 } 217 218 }