Mercurial > libervia-desktop-kivy
comparison cagou/core/xmlui.py @ 286:4772ba26623f
xmlui: many improvments:
- use a white background to be coherent with the rest of the UI
- cancel button is added on "window" XMLUIs
- use color for submit/save buttons
- VerticalContainer is not a ScrollView anymore, XMLUIPanel now has the main ScrollView
- when a TabsContainer is used as main container, main XMLUIPanel ScrollView touch events are disabled, to improve user experience (Kivy doesn't support well ScrollView inside an other ScrollView)
- use BoxLayout instead of GridLayout in AdvancedList*, as they use one row/col only
- fixed DividerWidget line location
- added margins in XMLUI panels
- renamed Settings main class to CagouSettings, to avoid conflict with Kivy's Settings class (which is causing troubles with kv)
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Mar 2019 22:22:51 +0100 |
parents | 1b835bcfa663 |
children | b2727877bad4 |
comparison
equal
deleted
inserted
replaced
285:3f7e227aab00 | 286:4772ba26623f |
---|---|
255 | 255 |
256 | 256 |
257 ## Containers ## | 257 ## Containers ## |
258 | 258 |
259 | 259 |
260 class VerticalContainer(xmlui.VerticalContainer, ScrollView): | 260 class VerticalContainer(xmlui.VerticalContainer, BoxLayout): |
261 layout = properties.ObjectProperty(None) | |
262 | 261 |
263 def __init__(self, xmlui_parent): | 262 def __init__(self, xmlui_parent): |
264 self.xmlui_parent = xmlui_parent | 263 self.xmlui_parent = xmlui_parent |
265 ScrollView.__init__(self) | 264 BoxLayout.__init__(self) |
266 | 265 |
267 def _xmluiAppend(self, widget): | 266 def _xmluiAppend(self, widget): |
268 self.layout.add_widget(widget) | 267 self.add_widget(widget) |
269 | 268 |
270 | 269 |
271 class PairsContainer(xmlui.PairsContainer, GridLayout): | 270 class PairsContainer(xmlui.PairsContainer, GridLayout): |
272 | 271 |
273 def __init__(self, xmlui_parent): | 272 def __init__(self, xmlui_parent): |
299 tab = TabsPanelContainer(text=label) | 298 tab = TabsPanelContainer(text=label) |
300 self.add_widget(tab) | 299 self.add_widget(tab) |
301 return tab | 300 return tab |
302 | 301 |
303 | 302 |
304 class AdvancedListRow(GridLayout): | 303 class AdvancedListRow(BoxLayout): |
305 global_index = 0 | 304 global_index = 0 |
306 index = properties.ObjectProperty() | 305 index = properties.ObjectProperty() |
307 selected = properties.BooleanProperty(False) | 306 selected = properties.BooleanProperty(False) |
308 | 307 |
309 def __init__(self, **kwargs): | 308 def __init__(self, **kwargs): |
323 self.selected = parent._xmluiToggleSelected(self) | 322 self.selected = parent._xmluiToggleSelected(self) |
324 | 323 |
325 return super(AdvancedListRow, self).on_touch_down(touch) | 324 return super(AdvancedListRow, self).on_touch_down(touch) |
326 | 325 |
327 | 326 |
328 class AdvancedListContainer(xmlui.AdvancedListContainer, GridLayout): | 327 class AdvancedListContainer(xmlui.AdvancedListContainer, BoxLayout): |
329 | 328 |
330 def __init__(self, xmlui_parent, columns, selectable='no'): | 329 def __init__(self, xmlui_parent, columns, selectable='no'): |
331 self.xmlui_parent = xmlui_parent | 330 self.xmlui_parent = xmlui_parent |
332 GridLayout.__init__(self) | 331 BoxLayout.__init__(self) |
333 self._columns = columns | 332 self._columns = columns |
334 self.selectable = selectable != 'no' | 333 self.selectable = selectable != 'no' |
335 self._current_row = None | 334 self._current_row = None |
336 self._selected = [] | 335 self._selected = [] |
337 self._xmlui_select_cb = None | 336 self._xmlui_select_cb = None |
374 | 373 |
375 def _xmluiOnSelect(self, callback): | 374 def _xmluiOnSelect(self, callback): |
376 """ Call callback with widget as only argument """ | 375 """ Call callback with widget as only argument """ |
377 self._xmlui_select_cb = callback | 376 self._xmlui_select_cb = callback |
378 | 377 |
378 | |
379 ## Dialogs ## | 379 ## Dialogs ## |
380 | 380 |
381 | 381 |
382 class NoteDialog(xmlui.NoteDialog): | 382 class NoteDialog(xmlui.NoteDialog): |
383 | 383 |
496 | 496 |
497 | 497 |
498 class FormButton(Button): | 498 class FormButton(Button): |
499 pass | 499 pass |
500 | 500 |
501 | 501 class SubmitButton(FormButton): |
502 class XMLUIPanel(xmlui.XMLUIPanel, BoxLayout): | 502 pass |
503 | |
504 class CancelButton(FormButton): | |
505 pass | |
506 | |
507 class SaveButton(FormButton): | |
508 pass | |
509 | |
510 | |
511 class XMLUIPanel(xmlui.XMLUIPanel, ScrollView): | |
503 widget_factory = WidgetFactory() | 512 widget_factory = WidgetFactory() |
513 layout = properties.ObjectProperty() | |
504 | 514 |
505 def __init__(self, host, parsed_xml, title=None, flags=None, callback=None, | 515 def __init__(self, host, parsed_xml, title=None, flags=None, callback=None, |
506 ignore=None, whitelist=None, profile=C.PROF_KEY_NONE): | 516 ignore=None, whitelist=None, profile=C.PROF_KEY_NONE): |
507 BoxLayout.__init__(self) | 517 ScrollView.__init__(self) |
508 self.close_cb = None | 518 self.close_cb = None |
509 self._post_treats = [] # list of callback to call after UI is constructed | 519 self._post_treats = [] # list of callback to call after UI is constructed |
520 | |
521 # used to workaround touch issues when a ScrollView is used inside this | |
522 # one. This happens notably when a TabsContainer is used as main container | |
523 # (this is the case with settings). | |
524 self._skip_scroll_events = False | |
510 xmlui.XMLUIPanel.__init__(self, | 525 xmlui.XMLUIPanel.__init__(self, |
511 host, | 526 host, |
512 parsed_xml, | 527 parsed_xml, |
513 title=title, | 528 title=title, |
514 flags=flags, | 529 flags=flags, |
515 callback=callback, | 530 callback=callback, |
516 ignore=ignore, | 531 ignore=ignore, |
517 whitelist=whitelist, | 532 whitelist=whitelist, |
518 profile=profile) | 533 profile=profile) |
534 self.bind(height=self.onHeight) | |
535 | |
536 def on_touch_down(self, touch, after=False): | |
537 if self._skip_scroll_events: | |
538 return super(ScrollView, self).on_touch_down(touch) | |
539 else: | |
540 return super(XMLUIPanel, self).on_touch_down(touch) | |
541 | |
542 def on_touch_up(self, touch, after=False): | |
543 if self._skip_scroll_events: | |
544 return super(ScrollView, self).on_touch_up(touch) | |
545 else: | |
546 return super(XMLUIPanel, self).on_touch_up(touch) | |
547 | |
548 def on_touch_move(self, touch, after=False): | |
549 if self._skip_scroll_events: | |
550 return super(ScrollView, self).on_touch_move(touch) | |
551 else: | |
552 return super(XMLUIPanel, self).on_touch_move(touch) | |
519 | 553 |
520 def setCloseCb(self, close_cb): | 554 def setCloseCb(self, close_cb): |
521 self.close_cb = close_cb | 555 self.close_cb = close_cb |
522 | 556 |
523 def _xmluiClose(self): | 557 def _xmluiClose(self, *__): |
524 if self.close_cb is not None: | 558 if self.close_cb is not None: |
525 self.close_cb(self) | 559 self.close_cb(self) |
526 else: | 560 else: |
527 G.host.closeUI() | 561 G.host.closeUI() |
528 | 562 |
543 self.onSaveParams(button) | 577 self.onSaveParams(button) |
544 | 578 |
545 def constructUI(self, parsed_dom): | 579 def constructUI(self, parsed_dom): |
546 xmlui.XMLUIPanel.constructUI(self, parsed_dom, self._postTreatCb) | 580 xmlui.XMLUIPanel.constructUI(self, parsed_dom, self._postTreatCb) |
547 if self.xmlui_title: | 581 if self.xmlui_title: |
548 self.add_widget(Title(text=self.xmlui_title)) | 582 self.layout.add_widget(Title(text=self.xmlui_title)) |
549 self.add_widget(self.main_cont) | 583 if isinstance(self.main_cont, TabsContainer): |
584 # cf. comments above | |
585 self._skip_scroll_events = True | |
586 self.layout.add_widget(self.main_cont) | |
550 if self.type == 'form': | 587 if self.type == 'form': |
551 submit_btn = FormButton(text=_(u"Submit")) | 588 submit_btn = SubmitButton() |
552 submit_btn.bind(on_press=self.onFormSubmitted) | 589 submit_btn.bind(on_press=self.onFormSubmitted) |
553 self.add_widget(submit_btn) | 590 self.layout.add_widget(submit_btn) |
554 if not 'NO_CANCEL' in self.flags: | 591 if not 'NO_CANCEL' in self.flags: |
555 cancel_btn = FormButton(text=_(u"Cancel")) | 592 cancel_btn = CancelButton(text=_(u"Cancel")) |
556 cancel_btn.bind(on_press=self.onFormCancelled) | 593 cancel_btn.bind(on_press=self.onFormCancelled) |
557 self.add_widget(cancel_btn) | 594 self.layout.add_widget(cancel_btn) |
558 elif self.type == 'param': | 595 elif self.type == 'param': |
559 self.save_btn = FormButton(text=_(u"Save"), disabled=True) | 596 self.save_btn = SaveButton(text=_(u"Save"), disabled=True) |
560 self.save_btn.bind(on_press=self._saveButtonCb) | 597 self.save_btn.bind(on_press=self._saveButtonCb) |
561 self.add_widget(self.save_btn) | 598 self.layout.add_widget(self.save_btn) |
599 elif self.type == 'window': | |
600 cancel_btn = CancelButton(text=_(u"Cancel")) | |
601 cancel_btn.bind(on_press=self._xmluiClose) | |
602 self.layout.add_widget(cancel_btn) | |
603 | |
604 def onHeight(self, __, height): | |
605 if isinstance(self.main_cont, TabsContainer): | |
606 # when the main | |
607 other_children_height = sum([c.height for c in self.layout.children | |
608 if c is not self.main_cont]) | |
609 self.main_cont.height = height - other_children_height | |
562 | 610 |
563 def show(self, *args, **kwargs): | 611 def show(self, *args, **kwargs): |
564 if not self.user_action and not kwargs.get("force", False): | 612 if not self.user_action and not kwargs.get("force", False): |
565 G.host.addNotifUI(self) | 613 G.host.addNotifUI(self) |
566 else: | 614 else: |