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):
32 class glGuiContainer(glGuiControl):
33 def __init__(self, parent, pos):
34 self._glGuiControlList = []
35 glGuiLayoutButtons(self)
36 super(glGuiContainer, self).__init__(parent, pos)
39 self._glGuiControlList.append(ctrl)
42 def OnMouseDown(self, x, y):
43 for ctrl in self._glGuiControlList:
44 if ctrl.OnMouseDown(x, y):
48 def OnMouseMotion(self, x, y):
50 for ctrl in self._glGuiControlList:
51 if ctrl.OnMouseMotion(x, y):
56 for ctrl in self._glGuiControlList:
59 def updateLayout(self):
61 for ctrl in self._glGuiControlList:
64 class glGuiPanel(glcanvas.GLCanvas):
65 def __init__(self, parent):
66 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
67 glcanvas.GLCanvas.__init__(self, parent, style=wx.WANTS_CHARS, attribList = attribList)
70 self._container = None
71 self._container = glGuiContainer(self, (0,0))
73 self._context = glcanvas.GLContext(self)
74 self._glButtonsTexture = None
77 wx.EVT_PAINT(self, self._OnGuiPaint)
78 wx.EVT_SIZE(self, self._OnSize)
79 wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
80 wx.EVT_LEFT_DOWN(self, self._OnGuiMouseLeftDown)
81 wx.EVT_MOTION(self, self._OnGuiMouseMotion)
82 wx.EVT_CHAR(self, self.OnKeyChar)
83 wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
85 def OnKeyChar(self, e):
86 if self._focus is not None:
87 self._focus.OnKeyChar(e.GetKeyCode())
90 def OnFocusLost(self, e):
94 def _OnGuiMouseLeftDown(self,e):
96 if self._container.OnMouseDown(e.GetX(), e.GetY()):
99 self.OnMouseLeftDown(e)
101 def _OnGuiMouseMotion(self,e):
103 if not self._container.OnMouseMotion(e.GetX(), e.GetY()):
104 self.OnMouseMotion(e)
106 def _OnGuiPaint(self, e):
107 h = self.GetSize().GetHeight()
108 w = self.GetSize().GetWidth()
109 oldButtonSize = self._buttonSize
113 self._buttonSize = 48
115 self._buttonSize = 64
117 self._buttonSize = 80
119 self._buttonSize = 96
120 if self._buttonSize != oldButtonSize:
121 self._container.updateLayout()
123 dc = wx.PaintDC(self)
124 self.SetCurrent(self._context)
131 if self._glButtonsTexture is None:
132 self._glButtonsTexture = opengl.loadGLTexture('glButtons.png')
134 glDisable(GL_DEPTH_TEST)
136 glDisable(GL_LIGHTING)
137 glColor4ub(255,255,255,255)
139 glMatrixMode(GL_PROJECTION)
141 size = self.GetSize()
142 glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
143 glMatrixMode(GL_MODELVIEW)
146 self._container.draw()
148 def _OnEraseBackground(self,event):
149 #Workaround for windows background redraw flicker.
153 self._container.setSize(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
154 self._container.updateLayout()
157 def OnMouseLeftDown(self,e):
159 def OnMouseMotion(self, e):
161 def OnPaint(self, e):
165 if self._container is not None:
166 self._container.add(ctrl)
168 class glGuiLayoutButtons(object):
169 def __init__(self, parent):
170 self._parent = parent
171 self._parent._layout = self
174 bs = self._parent._base._buttonSize
175 x0, y0, w, h = self._parent.getSize()
177 for ctrl in self._parent._glGuiControlList:
180 x = w + pos[0] * gridSize - bs * 0.2
182 x = pos[0] * gridSize + bs * 0.2
184 y = h + pos[1] * gridSize - bs * 0.2
186 y = pos[1] * gridSize + bs * 0.2
187 ctrl.setSize(x, y, gridSize, gridSize)
189 def getLayoutSize(self):
190 _, _, w, h = self._parent.getSize()
193 class glGuiLayoutGrid(object):
194 def __init__(self, parent):
195 self._parent = parent
196 self._parent._layout = self
200 borderSize = self._parent._base._buttonSize * 0.2
201 x0, y0, w, h = self._parent.getSize()
206 for ctrl in self._parent._glGuiControlList:
208 w, h = ctrl.getMinSize()
212 widths[x] = max(widths[x], w)
216 heights[y] = max(heights[y], h)
217 for ctrl in self._parent._glGuiControlList:
221 for n in xrange(0, x):
225 for n in xrange(0, y):
229 ctrl.setSize(x1, y1, widths[x], heights[y])
230 self._size = sum(widths.values()) + borderSize * 2, sum(heights.values()) + borderSize * 2
232 def getLayoutSize(self):
235 class glButton(glGuiControl):
236 def __init__(self, parent, imageID, tooltip, pos, callback):
237 super(glButton, self).__init__(parent, pos)
238 self._tooltip = tooltip
239 self._parent = parent
240 self._imageID = imageID
241 self._callback = callback
242 self._selected = False
245 self._disabled = False
247 def setSelected(self, value):
248 self._selected = value
250 def setHidden(self, value):
253 def setDisabled(self, value):
254 self._disabled = value
256 def getSelected(self):
257 return self._selected
259 def getMinSize(self):
260 return self._base._buttonSize, self._base._buttonSize
262 def _getPixelPos(self):
263 x0, y0, w, h = self.getSize()
264 return x0 + w / 2, y0 + h / 2
270 cx = (self._imageID % 4) / 4
271 cy = int(self._imageID / 4) / 4
272 bs = self._base._buttonSize
273 pos = self._getPixelPos()
276 glTranslatef(pos[0], pos[1], 0)
277 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
278 glEnable(GL_TEXTURE_2D)
284 glScalef(bs * scale, bs * scale, bs * scale)
286 glColor4ub(128,128,128,128)
288 glColor4ub(255,255,255,255)
290 glTexCoord2f(cx+0.25, cy)
291 glVertex2f( 0.5,-0.5)
293 glVertex2f(-0.5,-0.5)
294 glTexCoord2f(cx, cy+0.25)
295 glVertex2f(-0.5, 0.5)
296 glTexCoord2f(cx+0.25, cy+0.25)
297 glVertex2f( 0.5, 0.5)
299 glDisable(GL_TEXTURE_2D)
301 glColor4ub(0,0,0,255)
302 glTranslatef(0, -0.55, 0)
303 opengl.glDrawStringCenter(self._tooltip)
306 def _checkHit(self, x, y):
309 bs = self.getMinSize()[0]
310 pos = self._getPixelPos()
311 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
313 def OnMouseMotion(self, x, y):
314 if self._checkHit(x, y):
320 def OnMouseDown(self, x, y):
321 if self._checkHit(x, y):
326 class glFrame(glGuiContainer):
327 def __init__(self, parent, pos):
328 super(glFrame, self).__init__(parent, pos)
329 self._selected = False
333 def setSelected(self, value):
334 self._selected = value
336 def setHidden(self, value):
339 def getSelected(self):
340 return self._selected
342 def getMinSize(self):
343 return self._base._buttonSize, self._base._buttonSize
345 def _getPixelPos(self):
346 x0, y0, w, h = self.getSize()
353 bs = self._parent._buttonSize
354 pos = self._getPixelPos()
357 glTranslatef(pos[0], pos[1], 0)
358 glBindTexture(GL_TEXTURE_2D, self._parent._glButtonsTexture)
359 glEnable(GL_TEXTURE_2D)
361 size = self._layout.getLayoutSize()
362 glColor4ub(255,255,255,128)
365 glVertex2f( size[0], 0)
369 glVertex2f( 0, size[1])
371 glVertex2f( size[0], size[1])
373 glDisable(GL_TEXTURE_2D)
375 #Draw the controls on the frame
376 super(glFrame, self).draw()
378 def _checkHit(self, x, y):
381 pos = self._getPixelPos()
382 w, h = self._layout.getLayoutSize()
383 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
385 def OnMouseMotion(self, x, y):
386 super(glFrame, self).OnMouseMotion(x, y)
387 if self._checkHit(x, y):
393 def OnMouseDown(self, x, y):
394 if self._checkHit(x, y):
395 super(glFrame, self).OnMouseDown(x, y)
399 class glLabel(glGuiControl):
400 def __init__(self, parent, label, pos):
402 super(glLabel, self).__init__(parent, pos)
404 def getMinSize(self):
405 w, h = opengl.glGetStringSize(self._label)
408 def _getPixelPos(self):
409 x0, y0, w, h = self.getSize()
413 x, y, w, h = self.getSize()
416 glTranslatef(x, y, 0)
418 glColor4ub(255,255,255,128)
430 glTranslate(5, h - 5, 0)
431 glColor4ub(0,0,0,255)
432 opengl.glDrawStringLeft(self._label)
435 def _checkHit(self, x, y):
438 def OnMouseMotion(self, x, y):
441 def OnMouseDown(self, x, y):
444 class glNumberCtrl(glGuiControl):
445 def __init__(self, parent, value, pos, callback):
446 self._callback = callback
447 self._value = str(value)
450 self._inCallback = False
451 super(glNumberCtrl, self).__init__(parent, pos)
453 def setValue(self, value):
456 self._value = str(value)
458 def getMinSize(self):
459 w, h = opengl.glGetStringSize("VALUES")
462 def _getPixelPos(self):
463 x0, y0, w, h = self.getSize()
467 x, y, w, h = self.getSize()
470 glTranslatef(x, y, 0)
472 if self._base._focus == self:
473 glColor4ub(255,255,255,255)
475 glColor4ub(255,255,255,192)
487 glTranslate(5, h - 5, 0)
488 glColor4ub(0,0,0,255)
489 opengl.glDrawStringLeft(self._value)
490 if self._base._focus == self:
491 glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
492 opengl.glDrawStringLeft('|')
495 def _checkHit(self, x, y):
496 x1, y1, w, h = self.getSize()
497 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
499 def OnMouseMotion(self, x, y):
502 def OnMouseDown(self, x, y):
503 if self._checkHit(x, y):
504 self._base._focus = self
505 self._selectPos = len(self._value)
509 def OnKeyChar(self, c):
510 self._inCallback = True
513 self._selectPos = max(0, self._selectPos)
514 if c == wx.WXK_RIGHT:
516 self._selectPos = min(self._selectPos, len(self._value))
517 if c == wx.WXK_BACK and self._selectPos > 0:
518 self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
520 self._callback(self._value)
521 if c == wx.WXK_DELETE:
522 self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
523 self._callback(self._value)
524 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
525 self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
527 self._callback(self._value)
528 self._inCallback = False
530 class glCheckbox(glGuiControl):
531 def __init__(self, parent, value, pos, callback):
532 self._callback = callback
536 self._inCallback = False
537 super(glCheckbox, self).__init__(parent, pos)
539 def setValue(self, value):
542 self._value = str(value)
547 def getMinSize(self):
550 def _getPixelPos(self):
551 x0, y0, w, h = self.getSize()
555 x, y, w, h = self.getSize()
558 glTranslatef(x, y, 0)
561 glColor4ub(0,255,0,255)
563 glColor4ub(255,0,0,255)
577 def _checkHit(self, x, y):
578 x1, y1, w, h = self.getSize()
579 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
581 def OnMouseMotion(self, x, y):
584 def OnMouseDown(self, x, y):
585 if self._checkHit(x, y):
586 self._value = not self._value