ya2 · news · projects · code · about

removed uml diagrams
[pmachines.git] / ya2 / lib / p3d / gui.py
CommitLineData
8ee66edd
FC
1from inspect import getmro
2from panda3d.core import TextNode, Texture
3from direct.gui.DirectGuiGlobals import FLAT, ENTER, EXIT, DISABLED, NORMAL, \
4 B1PRESS
5from direct.showbase.DirectObject import DirectObject
6from direct.gui.DirectButton import DirectButton
7from direct.gui.DirectCheckButton import DirectCheckButton
8from direct.gui.DirectOptionMenu import DirectOptionMenu
9from direct.gui.OnscreenImage import OnscreenImage
10from direct.gui.DirectSlider import DirectSlider
11from direct.gui.DirectEntry import DirectEntry, ENTRY_FOCUS_STATE
12from direct.gui.DirectLabel import DirectLabel
13from direct.gui.DirectFrame import DirectFrame
14from direct.gui.OnscreenText import OnscreenText
15from direct.gui.DirectScrolledFrame import DirectScrolledFrame
53ddf3c3 16from ya2.observer import Subject
cb700bcc 17# from ya2.lib.ivals import Seq, Wait, PosIval, Func
8ee66edd
FC
18
19
20class CommonBase:
21
22 def set_widget(self):
53ddf3c3 23 from ya2.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \
8ee66edd 24 CheckBtn, Entry, Img, Text, ScrolledFrame
53ddf3c3 25 from ya2.lib.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \
8ee66edd
FC
26 OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \
27 ScrolledFrameMixin
28 self.__class__ = self.__class__ # for pylint
29 libwdg2wdg = {
30 FrameMixin: [Frame],
31 ScrolledFrameMixin: [ScrolledFrame],
32 SliderMixin: [Slider],
33 BtnMixin: [Btn, Label],
34 OptionMenuMixin: [OptionMenu],
35 CheckBtnMixin: [CheckBtn],
36 EntryMixin: [Entry],
37 ImgMixin: [Img, Text]}
38 for libwdg, wdgcls in libwdg2wdg.items():
39 if any(cls in getmro(self.__class__) for cls in wdgcls):
40 par_cls = libwdg
41 clsname = self.__class__.__name__ + 'Widget'
42 self.__class__ = type(clsname, (self.__class__, par_cls), {})
43 self.init(self)
44 if not hasattr(self, 'bind'): return
45 bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)]
46 list(map(lambda args: self.bind(*args), bind_args))
47
48 def set_enter_transition(self):
49 start_pos = self.get_pos()
50 pos = self.pos - (3.6, 0)
51 self.set_pos((pos.x, 1, pos.y))
52 Seq(
53 Wait(abs(pos.y - 1) / 4),
54 PosIval(self.get_np(), .5, start_pos)
55 ).start()
56
57 def set_exit_transition(self, destroy):
58 start_pos = self.get_pos()
59 end_pos = (self.pos.x + 3.6, 1, self.pos.y)
60 seq = Seq(
61 Wait(abs(self.pos.y - 1) / 4),
62 PosIval(self.get_np(), .5, end_pos),
63 Func(self.destroy if destroy else self.hide))
64 if not destroy: seq += Func(self.set_pos, start_pos)
65 seq.start()
66
67 def translate(self):
68 if hasattr(self, 'bind_transl'): self.wdg['text'] = self.bind_transl
69
70
71class P3dImg(CommonBase):
72
73 def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False,
74 foreground=False, parent=None):
75 self.img = OnscreenImage(
76 filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent)
77 if background: self.img.set_bin('background', 10)
78 alpha_formats = [12] # panda3d.core.texture.Frgba
79 if self.img.get_texture().get_format() in alpha_formats:
80 self.img.set_transparency(True)
81 if foreground: self.img.set_bin('gui-popup', 50)
82
83 def reparent_to(self, node): return self.img.reparent_to(node)
84 def show(self): return self.img.show()
85 def hide(self): return self.img.hide()
86 def set_shader(self, shader): return self.img.set_shader(shader)
87 def set_shader_input(self, name, val):
88 return self.img.set_shader_input(name, val)
89 def set_texture(self, texturestage, texture):
90 return self.img.set_texture(texturestage, texture)
91
92 def set_exit_transition(self, destroy):
93 start_pos = self.get_pos()
94 end_pos = (self.pos.x + 3.6, 1, self.pos.y)
95 seq = Seq(
96 Wait(abs(self.pos.y - 1) / 4),
97 PosIval(self.get_np(), .5, end_pos),
98 Func(self.destroy if destroy else self.hide))
99 if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2]))
100 seq.start()
101
102 def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1])
103
104 def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else [])
105
106 @property
107 def parent(self): return self.img.get_parent()
108
109 @property
110 def hidden(self): return self.img.is_hidden()
111
112 def set_transparent(self): return self.img.set_transparency(True)
113
114 def destroy(self): self.img = self.img.destroy()
115
116
cb700bcc 117# class P3dBase(CommonBase):
8ee66edd 118
cb700bcc
FC
119# def __init__(self, tra_src=None, tra_tra=None):
120# # self.text_src_tra = None # it breaks the gui
121# if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra)
8ee66edd 122
cb700bcc
FC
123# def set_pos(self, pos): return self.wdg.set_pos(pos)
124# def show(self): return self.wdg.show()
125# def hide(self): return self.wdg.hide()
8ee66edd 126
cb700bcc
FC
127# def bind_tra(self, text_src, text_transl):
128# # text_transl is not used, anyway we need it since we have this kind of
129# # use: self.bind_transl('example str', _('example str'))
130# # this allows to change translations on the fly keeping the source
131# # text for remapping it later
132# # TODO: try reverse mapping? i.e. retrieve the src string from the
133# # translated one
134# self.text_src_tra = text_src
135# self.text_tra_tra = text_transl
136# tra = lambda self: _(self.text_tra_tra)
137# self.__class__.bind_transl = property(tra)
138# self['text'] = self.bind_transl
8ee66edd 139
cb700bcc
FC
140# def get_pos(self, pos=None):
141# return self.wdg.get_pos(*[pos] if pos else [])
8ee66edd 142
cb700bcc 143# def __setitem__(self, key, value): self.wdg[key] = value
8ee66edd 144
cb700bcc
FC
145# def __getitem__(self, key): return self.wdg[key]
146
147# def get_np(self): return self.wdg
148
149# @property
150# def hidden(self): return self.wdg.is_hidden()
151
152# def destroy(self): self.wdg.destroy()
153
154
155# class P3dAbs(P3dBase):
156
157# def get_value(self): return self.wdg.getValue()
158# def initialiseoptions(self): return self.wdg.initialiseoptions()
159# def set_z(self, val): return self.wdg.set_z(val)
160# def set_shader(self, shader): return self.wdg.set_shader(shader)
161# def set_shader_input(self, name, val):
162# return self.wdg.set_shader_input(name, val)
163# def set_transparency(self, val): return self.wdg.set_transparency(val)
164# def bind(self, evt, mth): return self.wdg.bind(evt, mth)
165
166# def attachNewNode(self, gui_itm, sort_order):
167# # it won't work if we name it attach_node. hopefully this will be
168# # possible when we'll use decorators in place of mixins
169# return self.wdg.attachNewNode(gui_itm, sort_order)
170
171# @property
172# def is_enabled(self): return self.wdg['state'] != DISABLED
173
174
175# class P3dBtn(P3dAbs):
176
177# def __init__(
178# self, text='', parent=None, pos=(0, 0), scale=(1, 1),
179# cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None,
180# text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None,
181# over_snd=None, extra_args=None, frame_texture=None, img=None,
182# tra_src=None, tra_tra=None, text_scale=1.0):
183# str2par = {'bottomcenter': base.a2dBottomCenter}
184# parent = str2par.get(parent, parent)
185# extra_args = extra_args or []
186# self.wdg = DirectButton(
187# text=text, parent=parent, pos=(pos[0], 1, pos[1]),
188# scale=(scale[0], 1, scale[1]), command=cmd,
189# frameSize=frame_size, clickSound=click_snd, text_fg=text_fg,
190# frameColor=frame_col, text_font=text_font, rolloverSound=over_snd,
191# extraArgs=extra_args, frameTexture=frame_texture, image=img,
192# text_scale=text_scale)
193# P3dAbs.__init__(self, tra_src, tra_tra)
194# self['relief'] = FLAT
195# args = [(ENTER, self._on_enter), (EXIT, self._on_exit)]
196# list(map(lambda args: self.bind(*args), args))
197
198# def _on_enter(self, pos): pass # pos comes from mouse
199
200# def _on_exit(self, pos): pass # pos comes from mouse
201
202# # we add these with the mixins
203# # def enable(self): self['state'] = NORMAL
204
205# # def disable(self): self['state'] = DISABLED
206
207
208# class P3dSlider(P3dAbs):
209
210# def __init__(
211# self, parent=None, pos=(0, 0), scale=1, val=0,
212# frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1),
213# cmd=None, range_=(0, 1), tra_src=None, tra_tra=None):
214# self.wdg = DirectSlider(
215# parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val,
216# frameColor=frame_col, thumb_frameColor=thumb_frame_col,
217# command=cmd, range=range_)
218# P3dAbs.__init__(self, tra_src, tra_tra)
219
220
221# class P3dCheckBtn(P3dAbs):
222
223# def __init__(
224# self, pos=(0, 0), text='', indicator_val=False,
225# indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1),
226# scale=(1, 1, 1), click_snd=None, over_snd=None,
227# text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None,
228# tra_tra=None):
229# self.wdg = DirectCheckButton(
230# pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val,
231# indicator_frameColor=indicator_frame_col,
232# frameColor=frame_col, scale=scale, clickSound=click_snd,
233# rolloverSound=over_snd, text_fg=text_fg, text_font=text_font,
234# command=cmd)
235# P3dAbs.__init__(self, tra_src, tra_tra)
236
237
238# class P3dOptionMenu(P3dAbs):
239
240# def __init__(
241# self, text='', items=None, pos=(0, 0), scale=(1, 1, 1),
242# initialitem='', cmd=None, frame_size=(-1, 1, -1, 1),
243# click_snd=None, over_snd=None, text_may_change=False,
244# text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1),
245# frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1),
246# text_scale=.05, popup_marker_col=(1, 1, 1, 1),
247# item_relief=None, item_text_font=None, text_font=None,
248# tra_src=None, tra_tra=None):
249# items = items or []
250# self.wdg = DirectOptionMenu(
251# text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale,
252# initialitem=initialitem, command=cmd, frameSize=frame_size,
253# clickSound=click_snd, rolloverSound=over_snd,
254# textMayChange=text_may_change, text_fg=text_fg,
255# item_frameColor=item_frame_col, frameColor=frame_col,
256# highlightColor=highlight_col, text_scale=text_scale,
257# popupMarker_frameColor=popup_marker_col,
258# item_relief=item_relief, item_text_font=item_text_font,
259# text_font=text_font)
260# P3dAbs.__init__(self, tra_src, tra_tra)
261
262# def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
263
264# @property
265# def curr_val(self): return self.wdg.get()
266
267# @property
268# def curr_idx(self): return self.wdg.selectedIndex
269
270
271# class P3dEntry(P3dAbs, DirectObject, Subject):
272
273# def __init__(
274# self, scale=.05, pos=(0, 0), entry_font=None, width=12,
275# frame_col=(1, 1, 1, 1), initial_text='', obscured=False,
276# cmd=None, focus_in_cmd=None, focus_in_args=None,
277# focus_out_cmd=None, focus_out_args=None, parent=None,
278# tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None,
279# on_click=None):
280# self.__focused = False
281# self.__focus_in_cmd = focus_in_cmd
282# self.__focus_out_cmd = focus_out_cmd
283# DirectObject.__init__(self)
284# Subject.__init__(self)
285# focus_in_args = focus_in_args or []
286# focus_out_args = focus_out_args or []
287# self.wdg = DirectEntry(
288# scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font,
289# width=width, frameColor=frame_col, initialText=initial_text,
290# obscured=obscured, command=cmd, focusInCommand=self._focus_in_cmd,
291# focusInExtraArgs=focus_in_args,
292# focusOutCommand=self._focus_out_cmd,
293# focusOutExtraArgs=focus_out_args, parent=parent,
294# text_fg=text_fg)
295# P3dAbs.__init__(self, tra_src, tra_tra)
296# if on_tab:
297# self.on_tab_cb = on_tab
298# self.accept('tab-up', self.on_tab)
299# if on_click: self.wdg.bind(B1PRESS, on_click)
300
301# def set(self, txt): return self.wdg.set(txt)
302
303# def _focus_in_cmd(self, *args):
304# self.__focused = True
305# if self.__focus_in_cmd: self.__focus_in_cmd(*args)
306# self.notify('on_entry_enter')
307
308# def _focus_out_cmd(self, *args):
309# self.__focused = False
310# if self.__focus_out_cmd: self.__focus_out_cmd(*args)
311# self.notify('on_entry_exit')
312
313# def on_tab(self):
314# if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
315
316# @property
317# def focused(self): return self.__focused
318
319# @property
320# def text(self): return self.wdg.get()
321
322# def enter_text(self, txt):
323# return self.wdg.enterText(txt)
324
325# def enable(self): self['state'] = NORMAL
326
327# def disable(self): self['state'] = DISABLED
328
329# def destroy(self):
330# self.ignore('tab-up')
331# self.on_tab_cb = None
332# Subject.destroy(self)
333# P3dAbs.destroy(self)
334
335
336# class P3dLabel(P3dAbs):
337
338# def __init__(
339# self, text='', pos=(0, 0), parent=None, text_wordwrap=12,
340# text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05,
341# frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None, hpr=(0, 0, 0)):
342# self.wdg = DirectLabel(
343# text=text, pos=(pos[0], 1, pos[1]), parent=parent,
344# text_wordwrap=text_wordwrap, text_align=text_align,
345# text_fg=text_fg, text_font=text_font, scale=scale,
346# frameColor=frame_col, hpr=hpr)
347# P3dAbs.__init__(self, tra_src, tra_tra)
348
349# def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority)
350
351# def set_x(self, x): return self.wdg.set_x(x)
352
353# def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
354
355
356# class P3dTxt(P3dBase):
357
358# def __init__(
359# self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None,
360# fg=(1, 1, 1, 1), font=None, align=None, tra_src=None,
361# tra_tra=None):
362# str2par = {'bottomleft': base.a2dBottomLeft,
363# 'bottomright': base.a2dBottomRight,
364# 'leftcenter': base.a2dLeftCenter}
365# str2al = {'left': TextNode.A_left, 'right': TextNode.A_right,
366# 'center': TextNode.A_center}
367# if parent and parent in str2par: parent = str2par[parent]
368# if align: align = str2al[align]
369# self.wdg = OnscreenText(
370# text=txt, pos=pos, scale=scale, wordwrap=wordwrap,
371# parent=parent, fg=fg, font=font, align=align)
372# P3dBase.__init__(self, tra_src, tra_tra)
373
374# def set_r(self, r): return self.wdg.set_r(r)
375
376
377# class P3dFrame(P3dAbs):
378
379# def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1),
380# pos=(0, 0), parent=None, texture_coord=False):
381# P3dAbs.__init__(self)
382# self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col,
383# pos=(pos[0], 1, pos[1]), parent=parent)
384# if texture_coord: self.wdg['frameTexture'] = Texture()
385
386
387# class P3dScrolledFrame(P3dAbs):
388
389# def __init__(
390# self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1),
391# scrollbar_width=.05, frame_col=(1, 1, 1, 1),
392# pos=(0, 0), parent='topleft'):
393# P3dAbs.__init__(self)
394# par2p3d = {'topleft': base.a2dTopLeft}
395# if parent and parent in par2p3d: parent = par2p3d[parent]
396# self.wdg = DirectScrolledFrame(
397# frameSize=frame_sz,
398# canvasSize=canvas_sz,
399# scrollBarWidth=scrollbar_width,
400# frameColor=frame_col,
401# pos=(pos[0], 1, pos[1]),
402# parent=parent)
8ee66edd 403
cb700bcc
FC
404# @property
405# def canvas(self): return self.wdg.getCanvas()