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():
51 class glGuiContainer(glGuiControl):
52 def __init__(self, parent, pos):
53 self._glGuiControlList = []
54 glGuiLayoutButtons(self)
55 super(glGuiContainer, self).__init__(parent, pos)
58 self._glGuiControlList.append(ctrl)
61 def OnMouseDown(self, x, y):
62 for ctrl in self._glGuiControlList:
63 if ctrl.OnMouseDown(x, y):
67 def OnMouseMotion(self, x, y):
69 for ctrl in self._glGuiControlList:
70 if ctrl.OnMouseMotion(x, y):
75 for ctrl in self._glGuiControlList:
78 def updateLayout(self):
80 for ctrl in self._glGuiControlList:
83 class glGuiPanel(glcanvas.GLCanvas):
84 def __init__(self, parent):
85 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
86 glcanvas.GLCanvas.__init__(self, parent, style=wx.WANTS_CHARS, attribList = attribList)
89 self._container = None
90 self._container = glGuiContainer(self, (0,0))
92 self._context = glcanvas.GLContext(self)
93 self._glButtonsTexture = None
96 wx.EVT_PAINT(self, self._OnGuiPaint)
97 wx.EVT_SIZE(self, self._OnSize)
98 wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
99 wx.EVT_LEFT_DOWN(self, self._OnGuiMouseLeftDown)
100 wx.EVT_MOTION(self, self._OnGuiMouseMotion)
101 wx.EVT_CHAR(self, self.OnKeyChar)
102 wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
104 def OnKeyChar(self, e):
105 if self._focus is not None:
106 self._focus.OnKeyChar(e.GetKeyCode())
109 def OnFocusLost(self, e):
113 def _OnGuiMouseLeftDown(self,e):
115 if self._container.OnMouseDown(e.GetX(), e.GetY()):
118 self.OnMouseLeftDown(e)
120 def _OnGuiMouseMotion(self,e):
122 if not self._container.OnMouseMotion(e.GetX(), e.GetY()):
123 self.OnMouseMotion(e)
125 def _OnGuiPaint(self, e):
126 h = self.GetSize().GetHeight()
127 w = self.GetSize().GetWidth()
128 oldButtonSize = self._buttonSize
132 self._buttonSize = 48
134 self._buttonSize = 64
136 self._buttonSize = 80
138 self._buttonSize = 96
139 if self._buttonSize != oldButtonSize:
140 self._container.updateLayout()
142 dc = wx.PaintDC(self)
143 self.SetCurrent(self._context)
150 if self._glButtonsTexture is None:
151 self._glButtonsTexture = opengl.loadGLTexture('glButtons.png')
153 glDisable(GL_DEPTH_TEST)
155 glDisable(GL_LIGHTING)
156 glColor4ub(255,255,255,255)
158 glMatrixMode(GL_PROJECTION)
160 size = self.GetSize()
161 glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
162 glMatrixMode(GL_MODELVIEW)
165 self._container.draw()
167 def _OnEraseBackground(self,event):
168 #Workaround for windows background redraw flicker.
172 self._container.setSize(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
173 self._container.updateLayout()
176 def OnMouseLeftDown(self,e):
178 def OnMouseMotion(self, e):
180 def OnPaint(self, e):
184 if self._container is not None:
185 self._container.add(ctrl)
187 class glGuiLayoutButtons(object):
188 def __init__(self, parent):
189 self._parent = parent
190 self._parent._layout = self
193 bs = self._parent._base._buttonSize
194 x0, y0, w, h = self._parent.getSize()
196 for ctrl in self._parent._glGuiControlList:
199 x = w + pos[0] * gridSize - bs * 0.2
201 x = pos[0] * gridSize + bs * 0.2
203 y = h + pos[1] * gridSize - bs * 0.2
205 y = pos[1] * gridSize + bs * 0.2
206 ctrl.setSize(x, y, gridSize, gridSize)
208 def getLayoutSize(self):
209 _, _, w, h = self._parent.getSize()
212 class glGuiLayoutGrid(object):
213 def __init__(self, parent):
214 self._parent = parent
215 self._parent._layout = self
219 borderSize = self._parent._base._buttonSize * 0.2
220 x0, y0, w, h = self._parent.getSize()
225 for ctrl in self._parent._glGuiControlList:
227 w, h = ctrl.getMinSize()
231 widths[x] = max(widths[x], w)
235 heights[y] = max(heights[y], h)
236 for ctrl in self._parent._glGuiControlList:
240 for n in xrange(0, x):
244 for n in xrange(0, y):
248 ctrl.setSize(x1, y1, widths[x], heights[y])
249 self._size = sum(widths.values()) + borderSize * 2, sum(heights.values()) + borderSize * 2
251 def getLayoutSize(self):
254 class glButton(glGuiControl):
255 def __init__(self, parent, imageID, tooltip, pos, callback):
256 super(glButton, self).__init__(parent, pos)
257 self._tooltip = tooltip
258 self._parent = parent
259 self._imageID = imageID
260 self._callback = callback
261 self._selected = False
264 self._disabled = False
266 def setSelected(self, value):
267 self._selected = value
269 def setHidden(self, value):
272 def setDisabled(self, value):
273 self._disabled = value
275 def getSelected(self):
276 return self._selected
278 def getMinSize(self):
279 return self._base._buttonSize, self._base._buttonSize
281 def _getPixelPos(self):
282 x0, y0, w, h = self.getSize()
283 return x0 + w / 2, y0 + h / 2
289 cx = (self._imageID % 4) / 4
290 cy = int(self._imageID / 4) / 4
291 bs = self._base._buttonSize
292 pos = self._getPixelPos()
295 glTranslatef(pos[0], pos[1], 0)
296 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
297 glEnable(GL_TEXTURE_2D)
303 glScalef(bs * scale, bs * scale, bs * scale)
305 glColor4ub(128,128,128,128)
307 glColor4ub(255,255,255,255)
309 glTexCoord2f(cx+0.25, cy)
310 glVertex2f( 0.5,-0.5)
312 glVertex2f(-0.5,-0.5)
313 glTexCoord2f(cx, cy+0.25)
314 glVertex2f(-0.5, 0.5)
315 glTexCoord2f(cx+0.25, cy+0.25)
316 glVertex2f( 0.5, 0.5)
318 glDisable(GL_TEXTURE_2D)
320 glColor4ub(0,0,0,255)
321 glTranslatef(0, -0.55, 0)
322 opengl.glDrawStringCenter(self._tooltip)
325 def _checkHit(self, x, y):
328 bs = self.getMinSize()[0]
329 pos = self._getPixelPos()
330 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
332 def OnMouseMotion(self, x, y):
333 if self._checkHit(x, y):
339 def OnMouseDown(self, x, y):
340 if self._checkHit(x, y):
345 class glRadioButton(glButton):
346 def __init__(self, parent, imageID, tooltip, pos, group, callback):
347 super(glRadioButton, self).__init__(parent, imageID, tooltip, pos, self._onRadioSelect)
349 self._radioCallback = callback
350 self._group.append(self)
352 def setSelected(self, value):
353 self._selected = value
355 def _onRadioSelect(self):
356 for ctrl in self._group:
358 ctrl.setSelected(False)
359 if self.getSelected():
360 self.setSelected(False)
362 self.setSelected(True)
363 self._radioCallback()
365 class glFrame(glGuiContainer):
366 def __init__(self, parent, pos):
367 super(glFrame, self).__init__(parent, pos)
368 self._selected = False
372 def setSelected(self, value):
373 self._selected = value
375 def setHidden(self, value):
378 def getSelected(self):
379 return self._selected
381 def getMinSize(self):
382 return self._base._buttonSize, self._base._buttonSize
384 def _getPixelPos(self):
385 x0, y0, w, h = self.getSize()
392 bs = self._parent._buttonSize
393 pos = self._getPixelPos()
396 glTranslatef(pos[0], pos[1], 0)
397 glBindTexture(GL_TEXTURE_2D, self._parent._glButtonsTexture)
398 glEnable(GL_TEXTURE_2D)
400 size = self._layout.getLayoutSize()
401 glColor4ub(255,255,255,128)
404 glVertex2f( size[0], 0)
408 glVertex2f( 0, size[1])
410 glVertex2f( size[0], size[1])
412 glDisable(GL_TEXTURE_2D)
414 #Draw the controls on the frame
415 super(glFrame, self).draw()
417 def _checkHit(self, x, y):
420 pos = self._getPixelPos()
421 w, h = self._layout.getLayoutSize()
422 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
424 def OnMouseMotion(self, x, y):
425 super(glFrame, self).OnMouseMotion(x, y)
426 if self._checkHit(x, y):
432 def OnMouseDown(self, x, y):
433 if self._checkHit(x, y):
434 super(glFrame, self).OnMouseDown(x, y)
438 class glLabel(glGuiControl):
439 def __init__(self, parent, label, pos):
441 super(glLabel, self).__init__(parent, pos)
443 def getMinSize(self):
444 w, h = opengl.glGetStringSize(self._label)
447 def _getPixelPos(self):
448 x0, y0, w, h = self.getSize()
452 x, y, w, h = self.getSize()
455 glTranslatef(x, y, 0)
457 glColor4ub(255,255,255,128)
469 glTranslate(5, h - 5, 0)
470 glColor4ub(0,0,0,255)
471 opengl.glDrawStringLeft(self._label)
474 def _checkHit(self, x, y):
477 def OnMouseMotion(self, x, y):
480 def OnMouseDown(self, x, y):
483 class glNumberCtrl(glGuiControl):
484 def __init__(self, parent, value, pos, callback):
485 self._callback = callback
486 self._value = str(value)
489 self._inCallback = False
490 super(glNumberCtrl, self).__init__(parent, pos)
492 def setValue(self, value):
495 self._value = str(value)
497 def getMinSize(self):
498 w, h = opengl.glGetStringSize("VALUES")
501 def _getPixelPos(self):
502 x0, y0, w, h = self.getSize()
506 x, y, w, h = self.getSize()
509 glTranslatef(x, y, 0)
511 if self._base._focus == self:
512 glColor4ub(255,255,255,255)
514 glColor4ub(255,255,255,192)
526 glTranslate(5, h - 5, 0)
527 glColor4ub(0,0,0,255)
528 opengl.glDrawStringLeft(self._value)
529 if self._base._focus == self:
530 glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
531 opengl.glDrawStringLeft('|')
534 def _checkHit(self, x, y):
535 x1, y1, w, h = self.getSize()
536 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
538 def OnMouseMotion(self, x, y):
541 def OnMouseDown(self, x, y):
542 if self._checkHit(x, y):
547 def OnKeyChar(self, c):
548 self._inCallback = True
551 self._selectPos = max(0, self._selectPos)
552 if c == wx.WXK_RIGHT:
554 self._selectPos = min(self._selectPos, len(self._value))
557 value = float(self._value)
562 self._value = str(value)
563 self._callback(self._value)
566 value = float(self._value)
572 self._value = str(value)
573 self._callback(self._value)
574 if c == wx.WXK_BACK and self._selectPos > 0:
575 self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
577 self._callback(self._value)
578 if c == wx.WXK_DELETE:
579 self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
580 self._callback(self._value)
582 if wx.GetKeyState(wx.WXK_SHIFT):
586 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
587 self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
589 self._callback(self._value)
590 self._inCallback = False
593 self._base._focus = self
594 self._selectPos = len(self._value)
597 class glCheckbox(glGuiControl):
598 def __init__(self, parent, value, pos, callback):
599 self._callback = callback
603 self._inCallback = False
604 super(glCheckbox, self).__init__(parent, pos)
606 def setValue(self, value):
609 self._value = str(value)
614 def getMinSize(self):
617 def _getPixelPos(self):
618 x0, y0, w, h = self.getSize()
622 x, y, w, h = self.getSize()
625 glTranslatef(x, y, 0)
628 glColor4ub(0,255,0,255)
630 glColor4ub(255,0,0,255)
644 def _checkHit(self, x, y):
645 x1, y1, w, h = self.getSize()
646 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
648 def OnMouseMotion(self, x, y):
651 def OnMouseDown(self, x, y):
652 if self._checkHit(x, y):
653 self._value = not self._value