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
246 def setSelected(self, value):
247 self._selected = value
249 def setHidden(self, value):
252 def getSelected(self):
253 return self._selected
255 def getMinSize(self):
256 return self._base._buttonSize, self._base._buttonSize
258 def _getPixelPos(self):
259 x0, y0, w, h = self.getSize()
260 return x0 + w / 2, y0 + h / 2
266 cx = (self._imageID % 4) / 4
267 cy = int(self._imageID / 4) / 4
268 bs = self._base._buttonSize
269 pos = self._getPixelPos()
272 glTranslatef(pos[0], pos[1], 0)
273 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
274 glEnable(GL_TEXTURE_2D)
280 glScalef(bs * scale, bs * scale, bs * scale)
281 glColor4ub(255,255,255,255)
283 glTexCoord2f(cx+0.25, cy)
284 glVertex2f( 0.5,-0.5)
286 glVertex2f(-0.5,-0.5)
287 glTexCoord2f(cx, cy+0.25)
288 glVertex2f(-0.5, 0.5)
289 glTexCoord2f(cx+0.25, cy+0.25)
290 glVertex2f( 0.5, 0.5)
292 glDisable(GL_TEXTURE_2D)
294 glColor4ub(0,0,0,255)
295 glTranslatef(0, -0.55, 0)
296 opengl.glDrawStringCenter(self._tooltip)
299 def _checkHit(self, x, y):
302 bs = self.getMinSize()[0]
303 pos = self._getPixelPos()
304 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
306 def OnMouseMotion(self, x, y):
307 if self._checkHit(x, y):
313 def OnMouseDown(self, x, y):
314 if self._checkHit(x, y):
319 class glFrame(glGuiContainer):
320 def __init__(self, parent, pos):
321 super(glFrame, self).__init__(parent, pos)
322 self._selected = False
326 def setSelected(self, value):
327 self._selected = value
329 def setHidden(self, value):
332 def getSelected(self):
333 return self._selected
335 def getMinSize(self):
336 return self._base._buttonSize, self._base._buttonSize
338 def _getPixelPos(self):
339 x0, y0, w, h = self.getSize()
346 bs = self._parent._buttonSize
347 pos = self._getPixelPos()
350 glTranslatef(pos[0], pos[1], 0)
351 glBindTexture(GL_TEXTURE_2D, self._parent._glButtonsTexture)
352 glEnable(GL_TEXTURE_2D)
354 size = self._layout.getLayoutSize()
355 glColor4ub(255,255,255,128)
358 glVertex2f( size[0], 0)
362 glVertex2f( 0, size[1])
364 glVertex2f( size[0], size[1])
366 glDisable(GL_TEXTURE_2D)
368 #Draw the controls on the frame
369 super(glFrame, self).draw()
371 def _checkHit(self, x, y):
374 pos = self._getPixelPos()
375 w, h = self._layout.getLayoutSize()
376 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
378 def OnMouseMotion(self, x, y):
379 super(glFrame, self).OnMouseMotion(x, y)
380 if self._checkHit(x, y):
386 def OnMouseDown(self, x, y):
387 if self._checkHit(x, y):
388 super(glFrame, self).OnMouseDown(x, y)
392 class glLabel(glGuiControl):
393 def __init__(self, parent, label, pos):
395 super(glLabel, self).__init__(parent, pos)
397 def getMinSize(self):
398 w, h = opengl.glGetStringSize(self._label)
401 def _getPixelPos(self):
402 x0, y0, w, h = self.getSize()
406 x, y, w, h = self.getSize()
409 glTranslatef(x, y, 0)
411 glColor4ub(255,255,255,128)
423 glTranslate(5, h - 5, 0)
424 glColor4ub(0,0,0,255)
425 opengl.glDrawStringLeft(self._label)
428 def _checkHit(self, x, y):
431 def OnMouseMotion(self, x, y):
434 def OnMouseDown(self, x, y):
437 class glTextCtrl(glGuiControl):
438 def __init__(self, parent, value, pos, callback):
439 self._callback = callback
440 self._value = str(value)
443 self._inCallback = False
444 super(glTextCtrl, self).__init__(parent, pos)
446 def setValue(self, value):
449 self._value = str(value)
451 def getMinSize(self):
452 w, h = opengl.glGetStringSize("VALUES")
455 def _getPixelPos(self):
456 x0, y0, w, h = self.getSize()
460 x, y, w, h = self.getSize()
463 glTranslatef(x, y, 0)
465 if self._base._focus == self:
466 glColor4ub(255,255,255,255)
468 glColor4ub(255,255,255,192)
480 glTranslate(5, h - 5, 0)
481 glColor4ub(0,0,0,255)
482 opengl.glDrawStringLeft(self._value)
483 if self._base._focus == self:
484 glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
485 opengl.glDrawStringLeft('|')
488 def _checkHit(self, x, y):
489 x1, y1, w, h = self.getSize()
490 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
492 def OnMouseMotion(self, x, y):
495 def OnMouseDown(self, x, y):
496 if self._checkHit(x, y):
497 self._base._focus = self
498 self._selectPos = len(self._value)
502 def OnKeyChar(self, c):
503 self._inCallback = True
506 self._selectPos = max(0, self._selectPos)
507 if c == wx.WXK_RIGHT:
509 self._selectPos = min(self._selectPos, len(self._value))
510 if c == wx.WXK_BACK and self._selectPos > 0:
511 self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
513 self._callback(self._value)
514 if c == wx.WXK_DELETE:
515 self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
516 self._callback(self._value)
517 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
518 self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
520 self._callback(self._value)
521 self._inCallback = False
523 class glCheckbox(glGuiControl):
524 def __init__(self, parent, value, pos, callback):
525 self._callback = callback
529 self._inCallback = False
530 super(glCheckbox, self).__init__(parent, pos)
532 def setValue(self, value):
535 self._value = str(value)
540 def getMinSize(self):
543 def _getPixelPos(self):
544 x0, y0, w, h = self.getSize()
548 x, y, w, h = self.getSize()
551 glTranslatef(x, y, 0)
554 glColor4ub(0,255,0,255)
556 glColor4ub(255,0,0,255)
570 def _checkHit(self, x, y):
571 x1, y1, w, h = self.getSize()
572 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
574 def OnMouseMotion(self, x, y):
577 def OnMouseDown(self, x, y):
578 if self._checkHit(x, y):
579 self._value = not self._value