1 from __future__ import absolute_import
2 from __future__ import division
5 from wx import glcanvas
7 OpenGL.ERROR_CHECKING = False
8 from OpenGL.GL import *
10 from Cura.gui.util import opengl
12 class glGuiControl(object):
13 def __init__(self, parent, pos):
15 self._base = parent._base
17 self._size = (0,0, 1, 1)
18 self._parent.add(self)
20 def setSize(self, x, y, w, h):
21 self._size = (x, y, w, h)
29 def updateLayout(self):
33 for n in xrange(self._parent._glGuiControlList.index(self) + 1, len(self._parent._glGuiControlList)):
34 if self._parent._glGuiControlList[n].setFocus():
36 for n in xrange(0, self._parent._glGuiControlList.index(self)):
37 if self._parent._glGuiControlList[n].setFocus():
40 def focusPrevious(self):
41 for n in xrange(self._parent._glGuiControlList.index(self) -1, -1, -1):
42 if self._parent._glGuiControlList[n].setFocus():
44 for n in xrange(len(self._parent._glGuiControlList) - 1, self._parent._glGuiControlList.index(self), -1):
45 if self._parent._glGuiControlList[n].setFocus():
52 return self._base._focus == self
54 def OnKeyChar(self, key):
57 class glGuiContainer(glGuiControl):
58 def __init__(self, parent, pos):
59 self._glGuiControlList = []
60 glGuiLayoutButtons(self)
61 super(glGuiContainer, self).__init__(parent, pos)
64 self._glGuiControlList.append(ctrl)
67 def OnMouseDown(self, x, y):
68 for ctrl in self._glGuiControlList:
69 if ctrl.OnMouseDown(x, y):
73 def OnMouseMotion(self, x, y):
75 for ctrl in self._glGuiControlList:
76 if ctrl.OnMouseMotion(x, y):
81 for ctrl in self._glGuiControlList:
84 def updateLayout(self):
86 for ctrl in self._glGuiControlList:
89 class glGuiPanel(glcanvas.GLCanvas):
90 def __init__(self, parent):
91 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
92 glcanvas.GLCanvas.__init__(self, parent, style=wx.WANTS_CHARS, attribList = attribList)
95 self._container = None
96 self._container = glGuiContainer(self, (0,0))
98 self._context = glcanvas.GLContext(self)
99 self._glButtonsTexture = None
100 self._buttonSize = 64
102 wx.EVT_PAINT(self, self._OnGuiPaint)
103 wx.EVT_SIZE(self, self._OnSize)
104 wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
105 wx.EVT_LEFT_DOWN(self, self._OnGuiMouseLeftDown)
106 wx.EVT_MOTION(self, self._OnGuiMouseMotion)
107 wx.EVT_CHAR(self, self.OnKeyChar)
108 wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
110 def OnKeyChar(self, e):
111 if self._focus is not None:
112 self._focus.OnKeyChar(e.GetKeyCode())
115 def OnFocusLost(self, e):
119 def _OnGuiMouseLeftDown(self,e):
121 if self._container.OnMouseDown(e.GetX(), e.GetY()):
124 self.OnMouseLeftDown(e)
126 def _OnGuiMouseMotion(self,e):
128 if not self._container.OnMouseMotion(e.GetX(), e.GetY()):
129 self.OnMouseMotion(e)
131 def _OnGuiPaint(self, e):
132 h = self.GetSize().GetHeight()
133 w = self.GetSize().GetWidth()
134 oldButtonSize = self._buttonSize
138 self._buttonSize = 48
140 self._buttonSize = 64
142 self._buttonSize = 80
144 self._buttonSize = 96
145 if self._buttonSize != oldButtonSize:
146 self._container.updateLayout()
148 dc = wx.PaintDC(self)
149 self.SetCurrent(self._context)
156 if self._glButtonsTexture is None:
157 self._glButtonsTexture = opengl.loadGLTexture('glButtons.png')
159 glDisable(GL_DEPTH_TEST)
161 glDisable(GL_LIGHTING)
162 glColor4ub(255,255,255,255)
164 glMatrixMode(GL_PROJECTION)
166 size = self.GetSize()
167 glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
168 glMatrixMode(GL_MODELVIEW)
171 self._container.draw()
173 def _OnEraseBackground(self,event):
174 #Workaround for windows background redraw flicker.
178 self._container.setSize(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
179 self._container.updateLayout()
182 def OnMouseLeftDown(self,e):
184 def OnMouseMotion(self, e):
186 def OnPaint(self, e):
190 if self._container is not None:
191 self._container.add(ctrl)
193 class glGuiLayoutButtons(object):
194 def __init__(self, parent):
195 self._parent = parent
196 self._parent._layout = self
199 bs = self._parent._base._buttonSize
200 x0, y0, w, h = self._parent.getSize()
202 for ctrl in self._parent._glGuiControlList:
205 x = w + pos[0] * gridSize - bs * 0.2
207 x = pos[0] * gridSize + bs * 0.2
209 y = h + pos[1] * gridSize - bs * 0.2
211 y = pos[1] * gridSize + bs * 0.2
212 ctrl.setSize(x, y, gridSize, gridSize)
214 def getLayoutSize(self):
215 _, _, w, h = self._parent.getSize()
218 class glGuiLayoutGrid(object):
219 def __init__(self, parent):
220 self._parent = parent
221 self._parent._layout = self
225 borderSize = self._parent._base._buttonSize * 0.2
226 x0, y0, w, h = self._parent.getSize()
231 for ctrl in self._parent._glGuiControlList:
233 w, h = ctrl.getMinSize()
237 widths[x] = max(widths[x], w)
241 heights[y] = max(heights[y], h)
242 for ctrl in self._parent._glGuiControlList:
246 for n in xrange(0, x):
250 for n in xrange(0, y):
254 ctrl.setSize(x1, y1, widths[x], heights[y])
255 self._size = sum(widths.values()) + borderSize * 2, sum(heights.values()) + borderSize * 2
257 def getLayoutSize(self):
260 class glButton(glGuiControl):
261 def __init__(self, parent, imageID, tooltip, pos, callback):
262 super(glButton, self).__init__(parent, pos)
263 self._tooltip = tooltip
264 self._parent = parent
265 self._imageID = imageID
266 self._callback = callback
267 self._selected = False
270 self._disabled = False
272 def setSelected(self, value):
273 self._selected = value
275 def setHidden(self, value):
278 def setDisabled(self, value):
279 self._disabled = value
281 def getSelected(self):
282 return self._selected
284 def getMinSize(self):
285 return self._base._buttonSize, self._base._buttonSize
287 def _getPixelPos(self):
288 x0, y0, w, h = self.getSize()
289 return x0 + w / 2, y0 + h / 2
295 cx = (self._imageID % 4) / 4
296 cy = int(self._imageID / 4) / 4
297 bs = self._base._buttonSize
298 pos = self._getPixelPos()
301 glTranslatef(pos[0], pos[1], 0)
302 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
303 glEnable(GL_TEXTURE_2D)
309 glScalef(bs * scale, bs * scale, bs * scale)
311 glColor4ub(128,128,128,128)
313 glColor4ub(255,255,255,255)
315 glTexCoord2f(cx+0.25, cy)
316 glVertex2f( 0.5,-0.5)
318 glVertex2f(-0.5,-0.5)
319 glTexCoord2f(cx, cy+0.25)
320 glVertex2f(-0.5, 0.5)
321 glTexCoord2f(cx+0.25, cy+0.25)
322 glVertex2f( 0.5, 0.5)
324 glDisable(GL_TEXTURE_2D)
326 glColor4ub(0,0,0,255)
327 glTranslatef(0, -0.55, 0)
328 opengl.glDrawStringCenter(self._tooltip)
331 def _checkHit(self, x, y):
332 if self._hidden or self._disabled:
334 bs = self.getMinSize()[0]
335 pos = self._getPixelPos()
336 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
338 def OnMouseMotion(self, x, y):
339 if self._checkHit(x, y):
345 def OnMouseDown(self, x, y):
346 if self._checkHit(x, y):
351 class glRadioButton(glButton):
352 def __init__(self, parent, imageID, tooltip, pos, group, callback):
353 super(glRadioButton, self).__init__(parent, imageID, tooltip, pos, self._onRadioSelect)
355 self._radioCallback = callback
356 self._group.append(self)
358 def setSelected(self, value):
359 self._selected = value
361 def _onRadioSelect(self):
362 self._base._focus = None
363 for ctrl in self._group:
365 ctrl.setSelected(False)
366 if self.getSelected():
367 self.setSelected(False)
369 self.setSelected(True)
370 self._radioCallback()
372 class glComboButton(glButton):
373 def __init__(self, parent, tooltip, imageIDs, tooltips, pos, callback):
374 super(glComboButton, self).__init__(parent, imageIDs[0], tooltip, pos, self._onComboOpenSelect)
375 self._imageIDs = imageIDs
376 self._tooltips = tooltips
377 self._comboCallback = callback
380 def _onComboOpenSelect(self):
381 self._base._focus = self
386 self._selected = self.hasFocus()
387 super(glComboButton, self).draw()
388 if not self._selected:
391 bs = self._base._buttonSize / 2
392 pos = self._getPixelPos()
395 glTranslatef(pos[0]+bs*0.5, pos[1] + bs*0.5, 0)
396 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
398 for n in xrange(0, len(self._imageIDs)):
399 cx = (self._imageIDs[n] % 4) / 4
400 cy = int(self._imageIDs[n] / 4) / 4
401 glEnable(GL_TEXTURE_2D)
402 glTranslatef(0, 1, 0)
404 glColor4ub(128,128,128,128)
406 glColor4ub(255,255,255,255)
408 glTexCoord2f(cx+0.25, cy)
409 glVertex2f( 0.5,-0.5)
411 glVertex2f(-0.5,-0.5)
412 glTexCoord2f(cx, cy+0.25)
413 glVertex2f(-0.5, 0.5)
414 glTexCoord2f(cx+0.25, cy+0.25)
415 glVertex2f( 0.5, 0.5)
417 glDisable(GL_TEXTURE_2D)
420 glColor4ub(0,0,0,255)
421 glTranslatef(-0.55, 0.1, 0)
422 opengl.glDrawStringRight(self._tooltips[n])
427 return self._selection
429 def OnMouseDown(self, x, y):
430 if self._hidden or self._disabled:
433 bs = self._base._buttonSize / 2
434 pos = self._getPixelPos()
435 if 0 <= x - pos[0] <= bs and 0 <= y - pos[1] - bs <= bs * len(self._imageIDs):
436 self._selection = int((y - pos[1] - bs) / bs)
437 self._imageID = self._imageIDs[self._selection]
438 self._base._focus = None
439 self._comboCallback()
441 return super(glComboButton, self).OnMouseDown(x, y)
444 class glFrame(glGuiContainer):
445 def __init__(self, parent, pos):
446 super(glFrame, self).__init__(parent, pos)
447 self._selected = False
451 def setSelected(self, value):
452 self._selected = value
454 def setHidden(self, value):
457 def getSelected(self):
458 return self._selected
460 def getMinSize(self):
461 return self._base._buttonSize, self._base._buttonSize
463 def _getPixelPos(self):
464 x0, y0, w, h = self.getSize()
471 bs = self._parent._buttonSize
472 pos = self._getPixelPos()
475 glTranslatef(pos[0], pos[1], 0)
476 glBindTexture(GL_TEXTURE_2D, self._parent._glButtonsTexture)
477 glEnable(GL_TEXTURE_2D)
479 size = self._layout.getLayoutSize()
480 glColor4ub(255,255,255,128)
483 glVertex2f( size[0], 0)
487 glVertex2f( 0, size[1])
489 glVertex2f( size[0], size[1])
491 glDisable(GL_TEXTURE_2D)
493 #Draw the controls on the frame
494 super(glFrame, self).draw()
496 def _checkHit(self, x, y):
499 pos = self._getPixelPos()
500 w, h = self._layout.getLayoutSize()
501 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
503 def OnMouseMotion(self, x, y):
504 super(glFrame, self).OnMouseMotion(x, y)
505 if self._checkHit(x, y):
511 def OnMouseDown(self, x, y):
512 if self._checkHit(x, y):
513 super(glFrame, self).OnMouseDown(x, y)
517 class glLabel(glGuiControl):
518 def __init__(self, parent, label, pos):
520 super(glLabel, self).__init__(parent, pos)
522 def getMinSize(self):
523 w, h = opengl.glGetStringSize(self._label)
526 def _getPixelPos(self):
527 x0, y0, w, h = self.getSize()
531 x, y, w, h = self.getSize()
534 glTranslatef(x, y, 0)
536 glColor4ub(255,255,255,128)
548 glTranslate(5, h - 5, 0)
549 glColor4ub(0,0,0,255)
550 opengl.glDrawStringLeft(self._label)
553 def _checkHit(self, x, y):
556 def OnMouseMotion(self, x, y):
559 def OnMouseDown(self, x, y):
562 class glNumberCtrl(glGuiControl):
563 def __init__(self, parent, value, pos, callback):
564 self._callback = callback
565 self._value = str(value)
568 self._inCallback = False
569 super(glNumberCtrl, self).__init__(parent, pos)
571 def setValue(self, value):
574 self._value = str(value)
576 def getMinSize(self):
577 w, h = opengl.glGetStringSize("VALUES")
580 def _getPixelPos(self):
581 x0, y0, w, h = self.getSize()
585 x, y, w, h = self.getSize()
588 glTranslatef(x, y, 0)
591 glColor4ub(255,255,255,255)
593 glColor4ub(255,255,255,192)
605 glTranslate(5, h - 5, 0)
606 glColor4ub(0,0,0,255)
607 opengl.glDrawStringLeft(self._value)
609 glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
610 opengl.glDrawStringLeft('|')
613 def _checkHit(self, x, y):
614 x1, y1, w, h = self.getSize()
615 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
617 def OnMouseMotion(self, x, y):
620 def OnMouseDown(self, x, y):
621 if self._checkHit(x, y):
626 def OnKeyChar(self, c):
627 self._inCallback = True
630 self._selectPos = max(0, self._selectPos)
631 if c == wx.WXK_RIGHT:
633 self._selectPos = min(self._selectPos, len(self._value))
636 value = float(self._value)
641 self._value = str(value)
642 self._callback(self._value)
645 value = float(self._value)
651 self._value = str(value)
652 self._callback(self._value)
653 if c == wx.WXK_BACK and self._selectPos > 0:
654 self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
656 self._callback(self._value)
657 if c == wx.WXK_DELETE:
658 self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
659 self._callback(self._value)
661 if wx.GetKeyState(wx.WXK_SHIFT):
665 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
666 self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
668 self._callback(self._value)
669 self._inCallback = False
672 self._base._focus = self
673 self._selectPos = len(self._value)
676 class glCheckbox(glGuiControl):
677 def __init__(self, parent, value, pos, callback):
678 self._callback = callback
682 self._inCallback = False
683 super(glCheckbox, self).__init__(parent, pos)
685 def setValue(self, value):
688 self._value = str(value)
693 def getMinSize(self):
696 def _getPixelPos(self):
697 x0, y0, w, h = self.getSize()
701 x, y, w, h = self.getSize()
704 glTranslatef(x, y, 0)
707 glColor4ub(0,255,0,255)
709 glColor4ub(255,0,0,255)
723 def _checkHit(self, x, y):
724 x1, y1, w, h = self.getSize()
725 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
727 def OnMouseMotion(self, x, y):
730 def OnMouseDown(self, x, y):
731 if self._checkHit(x, y):
732 self._value = not self._value