Mercurial > libervia-web
comparison browser_side/panels.py @ 34:ed935f763cc8
browser side: misc css/layout fixes
- new ScrollPanelWrapper class, to try to handle correctly ScrollPanels in tables
- removed from EmptyPanel, because all td must appear empty, to use the absolute trick in ScrollPanelWrapper
- when an empty panel is changed to a normal panel, cells widths are recalculated
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 16 May 2011 03:10:11 +0200 |
parents | e70521e6d803 |
children | d43d6e4b9dc8 |
comparison
equal
deleted
inserted
replaced
33:e70521e6d803 | 34:ed935f763cc8 |
---|---|
22 import pyjd # this is dummy in pyjs | 22 import pyjd # this is dummy in pyjs |
23 from pyjamas.ui.SimplePanel import SimplePanel | 23 from pyjamas.ui.SimplePanel import SimplePanel |
24 from pyjamas.ui.FlowPanel import FlowPanel | 24 from pyjamas.ui.FlowPanel import FlowPanel |
25 from pyjamas.ui.AbsolutePanel import AbsolutePanel | 25 from pyjamas.ui.AbsolutePanel import AbsolutePanel |
26 from pyjamas.ui.VerticalPanel import VerticalPanel | 26 from pyjamas.ui.VerticalPanel import VerticalPanel |
27 from pyjamas.ui.DockPanel import DockPanel | |
27 from pyjamas.ui.HorizontalPanel import HorizontalPanel | 28 from pyjamas.ui.HorizontalPanel import HorizontalPanel |
28 from pyjamas.ui.ScrollPanel import ScrollPanel | 29 from pyjamas.ui.ScrollPanel import ScrollPanel |
29 from pyjamas.ui.TabPanel import TabPanel | 30 from pyjamas.ui.TabPanel import TabPanel |
30 from pyjamas.ui.HTMLPanel import HTMLPanel | 31 from pyjamas.ui.HTMLPanel import HTMLPanel |
31 from pyjamas.ui.PopupPanel import PopupPanel | 32 from pyjamas.ui.PopupPanel import PopupPanel |
148 _new_panel = MicroblogPanel(self.host, accept_all=True) | 149 _new_panel = MicroblogPanel(self.host, accept_all=True) |
149 self.host.mpanels.remove(self) | 150 self.host.mpanels.remove(self) |
150 self.host.mpanels.append(_new_panel) | 151 self.host.mpanels.append(_new_panel) |
151 grid = self.getParent() | 152 grid = self.getParent() |
152 row_idx, cell_idx = self._getCellAndRow(grid, event) | 153 row_idx, cell_idx = self._getCellAndRow(grid, event) |
153 self.removeFromParent() | |
154 if self.host.selected == self: | 154 if self.host.selected == self: |
155 self.host.select(None) | 155 self.host.select(None) |
156 self.removeFromParent() | |
156 grid.setWidget(row_idx, cell_idx, _new_panel) | 157 grid.setWidget(row_idx, cell_idx, _new_panel) |
158 _panels = list(grid) #this suppose that we only use 1 row, need to be changed in the futur | |
159 _unempty_panels = filter(lambda wid:not isinstance(wid,EmptyPanel),list(grid)) | |
160 _width = 90/float(len(_unempty_panels) or 1) | |
161 #now we resize all the cell of the column | |
162 for panel in _unempty_panels: | |
163 td_elt = panel.getElement().parentNode | |
164 DOM.setStyleAttribute(td_elt, "width", "%s%%" % _width) | |
157 #FIXME: delete object ? Check the right way with pyjamas | 165 #FIXME: delete object ? Check the right way with pyjamas |
166 | |
167 class ScrollPanelWrapper(SimplePanel): | |
168 """Scroll Panel like component, wich use the full available space | |
169 to work around percent size issue, it use some of the ideas found | |
170 here: http://code.google.com/p/google-web-toolkit/issues/detail?id=316 | |
171 specially in code given at comment #46, thanks to Stefan Bachert""" | |
172 | |
173 def __init__(self, *args, **kwargs): | |
174 SimplePanel.__init__(self) | |
175 self.spanel = ScrollPanel(*args, **kwargs) | |
176 SimplePanel.setWidget(self, self.spanel) | |
177 DOM.setStyleAttribute(self.getElement(), "position", "relative") | |
178 DOM.setStyleAttribute(self.getElement(), "top", "0px") | |
179 DOM.setStyleAttribute(self.getElement(), "left", "0px") | |
180 DOM.setStyleAttribute(self.getElement(), "width", "100%") | |
181 DOM.setStyleAttribute(self.getElement(), "height", "100%") | |
182 DOM.setStyleAttribute(self.spanel.getElement(), "position", "absolute") | |
183 DOM.setStyleAttribute(self.spanel.getElement(), "width", "100%") | |
184 DOM.setStyleAttribute(self.spanel.getElement(), "height", "100%") | |
185 | |
186 def setWidget(self, widget): | |
187 self.spanel.setWidget(widget) | |
188 | |
189 def setScrollPosition(self, position): | |
190 self.spanel.setScrollPosition(position) | |
191 | |
192 def scrollToBottom(self): | |
193 self.setScrollPosition(self.spanel.getElement().scrollHeight) | |
158 | 194 |
159 class EmptyPanel(DropCell, SimplePanel): | 195 class EmptyPanel(DropCell, SimplePanel): |
160 """Empty dropable panel""" | 196 """Empty dropable panel""" |
161 | 197 |
162 def __init__(self, host): | 198 def __init__(self, host): |
163 SimplePanel.__init__(self) | 199 SimplePanel.__init__(self) |
164 self.host = host | 200 self.host = host |
165 _panel = HTMLPanel(" ") | 201 _panel = HTMLPanel("") |
166 self.add(_panel) | 202 self.add(_panel) |
167 self.setHeight('50%') | 203 self.setHeight('100%') |
168 DropCell.__init__(self) | 204 DropCell.__init__(self) |
169 | 205 |
170 class UniBoxPanel(SimplePanel): | 206 class UniBoxPanel(SimplePanel): |
171 """Panel containing the UniBox""" | 207 """Panel containing the UniBox""" |
172 | 208 |
296 "body": body} | 332 "body": body} |
297 ) | 333 ) |
298 panel.setStyleName('microblogEntry') | 334 panel.setStyleName('microblogEntry') |
299 self.add(panel) | 335 self.add(panel) |
300 | 336 |
301 class MicroblogPanel(DropCell, ScrollPanel): | 337 class MicroblogPanel(DropCell, ScrollPanelWrapper): |
302 | 338 |
303 def __init__(self,host, title=' ', accept_all=False): | 339 def __init__(self,host, title=' ', accept_all=False): |
304 """Panel used to show microblog | 340 """Panel used to show microblog |
305 @param title: title of the panel | 341 @param title: title of the panel |
306 @param accept_all: if true, show every message, without filtering jids""" | 342 @param accept_all: if true, show every message, without filtering jids""" |
343 ScrollPanelWrapper.__init__(self) | |
344 DropCell.__init__(self) | |
307 self.host = host | 345 self.host = host |
308 self.accept_all = accept_all | 346 self.accept_all = accept_all |
309 title=title.replace('<','<').replace('>','>') | 347 title=title.replace('<','<').replace('>','>') |
310 self.accepted_groups = [] | 348 self.accepted_groups = [] |
311 _class = ['mb_panel_header'] | 349 _class = ['mb_panel_header'] |
312 if title == ' ': | 350 if title == ' ': |
313 _class.append('empty_header') | 351 _class.append('empty_header') |
314 ScrollPanel.__init__(self) | |
315 self.vpanel = VerticalPanel() | 352 self.vpanel = VerticalPanel() |
316 self.vpanel.add(HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title))) | 353 self.vpanel.add(HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title))) |
317 self.vpanel.setWidth('100%') | 354 self.vpanel.setWidth('100%') |
318 self.setHeight('50%') | |
319 self.setStyleName('microblogPanel') | 355 self.setStyleName('microblogPanel') |
320 self.add(self.vpanel) | 356 self.setWidget(self.vpanel) |
321 DropCell.__init__(self) | |
322 | 357 |
323 def addEntry(self, text, author=None, timestamp=None): | 358 def addEntry(self, text, author=None, timestamp=None): |
324 """Add an entry to the panel | 359 """Add an entry to the panel |
325 @param text: main text of the entry | 360 @param text: main text of the entry |
326 @param author: who wrote the entry | 361 @param author: who wrote the entry |
404 print "addOccupant: nick", nick | 439 print "addOccupant: nick", nick |
405 print _occupant | 440 print _occupant |
406 self.occupants.add(_occupant) | 441 self.occupants.add(_occupant) |
407 self.add(_occupant) | 442 self.add(_occupant) |
408 | 443 |
409 | 444 class ChatPanel(DropCell, ClickHandler, SimplePanel): |
410 | |
411 | |
412 class ChatPanel(DropCell, ClickHandler, AbsolutePanel): | |
413 | 445 |
414 def __init__(self, host, target, type='one2one'): | 446 def __init__(self, host, target, type='one2one'): |
415 """Panel used for conversation (one 2 one or group chat) | 447 """Panel used for conversation (one 2 one or group chat) |
416 @param host: SatWebFrontend instance | 448 @param host: SatWebFrontend instance |
417 @param target: entity (JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room) | 449 @param target: entity (JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room) |
418 @param type: one2one for simple conversation, group for MUC""" | 450 @param type: one2one for simple conversation, group for MUC""" |
451 SimplePanel.__init__(self) | |
452 DropCell.__init__(self) | |
453 ClickHandler.__init__(self) | |
454 self.vpanel = VerticalPanel() | |
455 self.vpanel.setSize('100%','100%') | |
419 self.host = host | 456 self.host = host |
420 self.type = type | 457 self.type = type |
421 self.nick = None | 458 self.nick = None |
422 if not target: | 459 if not target: |
423 print "ERROR: Empty target !" | 460 print "ERROR: Empty target !" |
424 return | 461 return |
425 self.target = target | 462 self.target = target |
426 title="%s" % target.bare | 463 title="%s" % target.bare |
427 title.replace('<','<').replace('>','>') | 464 title.replace('<','<').replace('>','>') |
428 _class = ['mb_panel_header'] | 465 _class = ['mb_panel_header'] |
429 AbsolutePanel.__init__(self) | |
430 self.header = HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title)) | 466 self.header = HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title)) |
467 self.header.setStyleName('chatHeader') | |
431 self.body = AbsolutePanel() | 468 self.body = AbsolutePanel() |
432 self.body.setStyleName('chatPanel_body') | 469 self.body.setStyleName('chatPanel_body') |
433 #self.body.setWidth('100%') | |
434 #self.body.setHeight('50%') | |
435 chat_area = HorizontalPanel() | 470 chat_area = HorizontalPanel() |
436 chat_area.setStyleName('chatArea') | 471 chat_area.setStyleName('chatArea') |
437 #chat_area.setHeight('50%') | |
438 if type == 'group': | 472 if type == 'group': |
439 self.occupants_list = OccupantsList() | 473 self.occupants_list = OccupantsList() |
440 chat_area.add(self.occupants_list) | 474 chat_area.add(self.occupants_list) |
441 self.body.add(chat_area) | 475 self.body.add(chat_area) |
442 self.content = AbsolutePanel() | 476 self.content = AbsolutePanel() |
443 self.content.setStyleName('chatContent') | 477 self.content.setStyleName('chatContent') |
444 #_scrollp.setHeight('50%') | 478 self.content_scroll = ScrollPanelWrapper(self.content) |
445 #_scrollp.setWidth('100%') | 479 chat_area.add(self.content_scroll) |
446 chat_area.add(ScrollPanel(self.content, Size=("100%", "100%"))) | 480 chat_area.setCellWidth(self.content_scroll, '100%') |
447 self.add(self.header) | 481 self.vpanel.add(self.header) |
448 self.add(self.body) | 482 self.vpanel.setCellHeight(self.header, '1%') |
449 #self.content.setWidth('100%') | 483 self.vpanel.add(self.body) |
450 #self.main_panel.setVerticalAlignment(HasAlignment.ALIGN_TOP) | 484 self.setWidget(self.vpanel) |
451 #self.body.setVerticalAlignment(HasAlignment.ALIGN_TOP) | |
452 #chat_area.setVerticalAlignment(HasAlignment.ALIGN_TOP) | |
453 #self.setWidth('100%') | |
454 #self.setHeight('50%') | |
455 self.setStyleName('chatPanel') | 485 self.setStyleName('chatPanel') |
456 DropCell.__init__(self) | |
457 ClickHandler.__init__(self) | |
458 self.addClickListener(self) | 486 self.addClickListener(self) |
459 | 487 |
460 def onClick(self, sender, event): | 488 def onClick(self, sender, event): |
461 self.host.select(self) | 489 self.host.select(self) |
462 | 490 |
486 mymess = _jid.resource == self.nick if self.type == "group" else _jid.bare == self.host.whoami.bare #mymess = True if message comes from local user | 514 mymess = _jid.resource == self.nick if self.type == "group" else _jid.bare == self.host.whoami.bare #mymess = True if message comes from local user |
487 """if msg.startswith('/me '): | 515 """if msg.startswith('/me '): |
488 self.printInfo('* %s %s' % (nick, msg[4:]),type='me') | 516 self.printInfo('* %s %s' % (nick, msg[4:]),type='me') |
489 return""" | 517 return""" |
490 self.content.add(ChatText(timestamp, nick, mymess, msg)) | 518 self.content.add(ChatText(timestamp, nick, mymess, msg)) |
491 | 519 self.content_scroll.scrollToBottom() |
492 class MainDiscussionPannel(HorizontalPanel): | 520 |
521 class MainDiscussionPanel(HorizontalPanel): | |
493 | 522 |
494 def __init__(self, host): | 523 def __init__(self, host): |
495 self.host=host | 524 self.host=host |
496 HorizontalPanel.__init__(self) | 525 HorizontalPanel.__init__(self) |
497 self._left = self.host.contact_panel | 526 self._left = self.host.contact_panel |
498 self._right = Grid(1,3) | 527 self._right = Grid(1,3) |
499 self._right.setWidth('100%') | 528 self._right.setWidth('100%') |
500 self._right.setHeight('50%') | 529 self._right.setHeight('100%') |
501 self.add(self._left) | 530 self.add(self._left) |
502 self.setCellWidth(self._left, "15%") | 531 self.setCellWidth(self._left, "15%") |
503 self.add(self._right) | 532 self.add(self._right) |
504 self.setCellWidth(self._right, "85%") | 533 self.setCellWidth(self._right, "85%") |
505 self.setHeight('50%') | |
506 | 534 |
507 def changePanel(self, idx, panel): | 535 def changePanel(self, idx, panel): |
508 self._right.setWidget(0,idx,panel) | 536 self._right.setWidget(0,idx,panel) |
509 | 537 self._right.getCellFormatter().setWidth(0, idx, '5%' if isinstance(panel, EmptyPanel) else '90%') |
510 class MainTabPannel(TabPanel): | 538 |
539 class MainTabPanel(TabPanel): | |
511 | 540 |
512 def __init__(self, host): | 541 def __init__(self, host): |
513 TabPanel.__init__(self) | 542 TabPanel.__init__(self) |
514 self.host=host | 543 self.host=host |
515 TabPanel() | 544 TabPanel() |
525 print ("ERROR: not TabBar found, it should exist !") | 554 print ("ERROR: not TabBar found, it should exist !") |
526 tab_bar_h = 0 | 555 tab_bar_h = 0 |
527 else: | 556 else: |
528 tab_bar_h = _elts.item(0).offsetHeight | 557 tab_bar_h = _elts.item(0).offsetHeight |
529 ideal_height = Window.getClientHeight() - tab_panel_elt.offsetTop - tab_bar_h - 5 | 558 ideal_height = Window.getClientHeight() - tab_panel_elt.offsetTop - tab_bar_h - 5 |
530 print "ideal_height =",ideal_height | |
531 self.setWidth("%s%s" % (width-5, "px")); | 559 self.setWidth("%s%s" % (width-5, "px")); |
532 self.setHeight("%s%s" % (ideal_height, "px")); | 560 self.setHeight("%s%s" % (ideal_height, "px")); |
533 | 561 |
534 def add(self, widget, tabText=None, asHTML=False): | 562 def add(self, widget, tabText=None, asHTML=False): |
535 TabPanel.add(self, widget, tabText, asHTML) | 563 TabPanel.add(self, widget, tabText, asHTML) |
536 if self.getWidgetCount()>1: | 564 if self.getWidgetCount()>1: |
537 self.tabBar.setVisible(True) | 565 self.tabBar.setVisible(True) |
538 self.host.resize() | 566 self.host.resize() |
539 | 567 |
540 """class MainTabPannel(FlowPanel): | |
541 | |
542 def __init__(self, host): | |
543 FlowPanel.__init__(self) | |
544 self.host=host | |
545 self.tab_panel = TabPanel() | |
546 self.tab_panel.tabBar.setVisible(False) | |
547 self.addStyleName('mainTabPanel') | |
548 FlowPanel.add(self, self.tab_panel) | |
549 self.tab_panel.setWidth('100%') | |
550 self.tab_panel.setHeight('100%') | |
551 Window.addWindowResizeListener(self) | |
552 | |
553 def onWindowResized(self, width, height): | |
554 print "onWindowResized" | |
555 tab_panel_elt = self.getElement() | |
556 _elts = doc().getElementsByClassName('gwt-TabBar') | |
557 if not _elts.length: | |
558 print ("ERROR: not TabBar found, it should exist !") | |
559 tab_bar_h = 0 | |
560 else: | |
561 tab_bar_h = _elts.item(0).offsetHeight | |
562 ideal_height = Window.getClientHeight() - tab_panel_elt.offsetTop - tab_bar_h - 5 | |
563 print "ideal_height =",ideal_height | |
564 self.setWidth("%s%s" % (width-5, "px")); | |
565 self.setHeight("%s%s" % (ideal_height, "px")); | |
566 | |
567 def selectTab(self, idx): | |
568 self.tab_panel.selectTab(idx) | |
569 | |
570 def add(self, widget, tabText=None, asHTML=False): | |
571 self.tab_panel.add(widget, tabText, asHTML) | |
572 if self.tab_panel.getWidgetCount()>1: | |
573 self.tab_panel.tabBar.setVisible(True) | |
574 self.host.resize()""" | |
575 | |
576 class MainPanel(AbsolutePanel): | 568 class MainPanel(AbsolutePanel): |
577 | 569 |
578 def __init__(self, host): | 570 def __init__(self, host): |
579 self.host=host | 571 self.host=host |
580 AbsolutePanel.__init__(self) | 572 AbsolutePanel.__init__(self) |
584 | 576 |
585 menu = Menu(host) | 577 menu = Menu(host) |
586 unibox_panel = UniBoxPanel(host) | 578 unibox_panel = UniBoxPanel(host) |
587 self.host.setUniBox(unibox_panel.unibox) | 579 self.host.setUniBox(unibox_panel.unibox) |
588 status = host.status_panel | 580 status = host.status_panel |
589 self.tab_panel = MainTabPannel(host) | 581 self.tab_panel = MainTabPanel(host) |
590 #self.tab_panel.setWidth('100%') | 582 self.discuss_panel = MainDiscussionPanel(self.host) |
591 #self.tab_panel.setHeight('50%') | |
592 self.discuss_panel = MainDiscussionPannel(self.host) | |
593 self.discuss_panel.setWidth('100%') | |
594 self.discuss_panel.setHeight('50%') | |
595 self.tab_panel.add(self.discuss_panel, "Discussions") | 583 self.tab_panel.add(self.discuss_panel, "Discussions") |
596 self.tab_panel.selectTab(0) | 584 self.tab_panel.selectTab(0) |
597 | 585 |
598 self.add(menu) | 586 self.add(menu) |
599 self.add(unibox_panel) | 587 self.add(unibox_panel) |
600 self.add(status) | 588 self.add(status) |
601 self.add(self.tab_panel) | 589 self.add(self.tab_panel) |
602 #self.tab_panel.onWindowResized(Window.getClientWidth(), Window.getClientHeight()) | |
603 | 590 |
604 """self.setCellHeight(menu, "5%") | |
605 self.setCellHeight(uni_box, "5%") | |
606 self.setCellVerticalAlignment(uni_box, HasAlignment.ALIGN_CENTER) | |
607 self.setCellHorizontalAlignment(uni_box, HasAlignment.ALIGN_CENTER) | |
608 self.setCellHeight(self.tab_panel, "90%") | |
609 self.setCellWidth(self.tab_panel, "100%")""" | |
610 | |
611 self.setWidth("100%") | 591 self.setWidth("100%") |
612 #self.setHeight("99%") | 592 #self.setHeight("99%") |
613 Window.addWindowResizeListener(self) | 593 Window.addWindowResizeListener(self) |
614 | 594 |
615 def onWindowResized(self, width, height): | 595 def onWindowResized(self, width, height): |