PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/peppy-0.16.0/peppy/lib/controls.py

#
Python | 773 lines | 739 code | 3 blank | 31 comment | 3 complexity | 098a293c2ae7be1d18d04045bfce347c MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0
  1. #-----------------------------------------------------------------------------
  2. # Name: controls.py
  3. # Purpose: miscellaneous wxPython controls
  4. #
  5. # Author: Rob McMullen
  6. #
  7. # Created: 2007
  8. # RCS-ID: $Id: $
  9. # Copyright: (c) 2007 Rob McMullen
  10. # License: wxWidgets
  11. #-----------------------------------------------------------------------------
  12. """Miscellaneous wx controls.
  13. This file contains various wx controls that don't have any
  14. dependencies on other parts of peppy.
  15. """
  16. import os, weakref, time
  17. from cStringIO import StringIO
  18. import wx
  19. from wx.lib import buttons
  20. from wx.lib import imageutils
  21. from wx.lib.pubsub import Publisher
  22. from wx.lib.filebrowsebutton import *
  23. import wx.gizmos
  24. from peppy.lib.iconstorage import *
  25. try:
  26. from peppy.debug import *
  27. except:
  28. def dprint(txt=""):
  29. #print txt
  30. pass
  31. if not '_' in dir():
  32. _ = unicode
  33. class TreeListCtrl(wx.gizmos.TreeListCtrl):
  34. def getText(self, parent=None, cookie=None, fh=None, indent=""):
  35. if parent is None:
  36. fh = StringIO()
  37. parent = self.GetRootItem()
  38. (child, cookie) = self.GetFirstChild(parent)
  39. while child.IsOk():
  40. text = "\t".join([self.GetItemText(child, i) for i in range(self.GetColumnCount())])
  41. fh.write("%s%s%s" % (indent, text, os.linesep))
  42. if self.ItemHasChildren(child) and self.IsExpanded(child):
  43. self.getText(child, cookie, fh, indent + " ")
  44. (child, cookie) = self.GetNextChild(parent, cookie)
  45. if not indent:
  46. return fh.getvalue()
  47. class StatusBarButton(wx.lib.buttons.GenBitmapButton):
  48. """A minimally sized bitmap button for use in the statusbar.
  49. This is a small-sized button for use in the status bar that
  50. doesn't have the usual button highlight or button-pressed cues.
  51. Trying to mimic the Mozilla statusbar buttons as much as possible.
  52. """
  53. labelDelta = 0
  54. def AcceptsFocus(self):
  55. return False
  56. def _GetLabelSize(self):
  57. """ used internally """
  58. if not self.bmpLabel:
  59. return -1, -1, False
  60. return self.bmpLabel.GetWidth(), self.bmpLabel.GetHeight(), False
  61. def DoGetBestSize(self):
  62. """
  63. Overridden base class virtual. Determines the best size of the
  64. button based on the label and bezel size.
  65. """
  66. width, height, useMin = self._GetLabelSize()
  67. return (width, height)
  68. def GetBackgroundBrush(self, dc):
  69. return None
  70. class ModularStatusBarInfo(object):
  71. """Data object used to store the state of a particular major mode's status
  72. bar.
  73. This is a flyweight object -- the data stored here is applied to the
  74. L{ModularStatusBar} instance that actually contains the controls.
  75. """
  76. def __init__(self, parent, widths=[-1, 150]):
  77. self.parent = parent
  78. self.widths = widths
  79. self.cancel_label = _("Cancel")
  80. self.text = [' ' for w in self.widths]
  81. self.gauge_value = 0
  82. self.gauge_width = 100
  83. self.gauge_max = 100
  84. self.gauge_text = None
  85. self.gauge_delay = 0
  86. self.gauge_start_time = 0
  87. self.gauge_shown = False
  88. self.gauge_refresh_trigger = 0
  89. self.gauge_refresh_count = 0
  90. self.disable_during_progress = False
  91. self.message = None
  92. self.overlays = []
  93. self.active_controls = []
  94. self.show_cancel = False
  95. self.cancelled = False
  96. self.debug_progress = False
  97. self.resetProgress()
  98. def resetProgress(self):
  99. """Reset the parent's state based on the info contained in this object
  100. Because this class is a Flyweight, the parent's controls are updated
  101. using the data contained in this object, and this method forces the
  102. objects back to the state that this major mode is expecting. For
  103. example, it resets the progress bar max value to the value that was
  104. last set by this major mode.
  105. """
  106. if self.parent.info == self:
  107. self.parent.setWidths()
  108. self.parent.gauge.SetRange(self.gauge_max)
  109. # Force gauge text to be reset
  110. text = self.gauge_text
  111. self.gauge_text = None
  112. self.setProgressPosition(self.gauge_value, text)
  113. if self.debug_progress: dprint("Reset progress: %s" % text)
  114. def resetIcons(self):
  115. """Reset the status bar so no icons are visible"""
  116. self.active_controls = []
  117. def addIcon(self, bmp, tooltip=None):
  118. """Append an icon to the right side of the status bar"""
  119. b = self.parent.getIcon(bmp, tooltip)
  120. self.active_controls.append(b)
  121. if self.parent.info == self:
  122. self.parent.setWidths()
  123. def setText(self, text, field=0):
  124. self.text[field] = text
  125. if self.parent.info == self:
  126. self.parent.SetStatusText(text, field)
  127. def getLastMessage(self, field=0):
  128. return self.text[field]
  129. def startProgress(self, text, max=100, cancel=False, message=None, delay=0, disable=False):
  130. """Create a progress meter in the status bar.
  131. Creates a gauge in the status bar with optional cancel button. Unless
  132. a delay is used, it is up to the user to call wx.Yield to show the
  133. progress bar.
  134. If a delay is used, wx.Yield will be called after the initial delay and
  135. during calls to updateProgress after the same number of ticks pass as
  136. occurred during the initial delay.
  137. @param text: text to display to the left of the progress bar
  138. @param max: maximum number of ticks in the gauge
  139. @param cancel: (optional) True to display a cancel button
  140. @param message: (optional) wx.lib.pubsub message that will be listened
  141. for to update the progress bar
  142. @param delay: (optional) delay in seconds before displaying the gauge.
  143. This can be used if the length of the operation is unknown but want
  144. to avoid the progress bar if it turns out to be quick.
  145. """
  146. if self.debug_progress: dprint("Start progress: %s, msg=%s max=%d" % (text, message, max))
  147. self.in_progress = True
  148. self.gauge_max = max
  149. self.cancelled = False
  150. self.show_cancel = cancel
  151. self.disable_during_progress = disable
  152. self.gauge_text = text
  153. self.gauge_delay = delay
  154. self.gauge_show_time = time.time() + delay
  155. self.gauge_shown = False
  156. self.gauge_refresh_trigger = 0
  157. self.gauge_refresh_count = 0
  158. self.overlays = []
  159. self.overlays.append((self.parent.gauge, self.gauge_width))
  160. if self.show_cancel:
  161. dc=wx.ClientDC(self.parent)
  162. tw, th = dc.GetTextExtent(self.cancel_label)
  163. tw += 20 # add some padding to the text for button border
  164. self.overlays.append((self.parent.cancel, tw))
  165. if message:
  166. Publisher().subscribe(self.updateMessage, message)
  167. self.message = message
  168. self.updateProgress(0)
  169. if self.gauge_delay == 0:
  170. if self.parent.info == self:
  171. self._showProgress()
  172. self.gauge_shown = True
  173. def _showProgress(self, max=None):
  174. if max is not None:
  175. self.gauge_max = max
  176. self.parent.gauge.SetRange(self.gauge_max)
  177. self.setText(self.gauge_text)
  178. self.parent.setWidths()
  179. def setProgressPosition(self, value, text=None, max=None):
  180. """Set the progress bar and text to the current values
  181. This is used to set the text and gauge position based on the current
  182. values stored in this info object.
  183. """
  184. if self.gauge_shown:
  185. if value < 0:
  186. self.parent.gauge.Pulse()
  187. else:
  188. if max is not None:
  189. self.gauge_max = max
  190. self.parent.gauge.SetRange(self.gauge_max)
  191. if self.debug_progress: dprint("update position: %s, msg=%s val=%d, max=%d" % (text, self.message, value, self.gauge_max))
  192. if value > self.gauge_max:
  193. value = self.gauge_max
  194. self.parent.gauge.SetValue(value)
  195. self.gauge_value = value
  196. if text is not None:
  197. if text != self.gauge_text:
  198. self.setText(text)
  199. self.gauge_text = text
  200. def updateProgress(self, value, text=None, max=None):
  201. """Update the progress bar with a new value
  202. @param value: either a number or a list. If it is a number, it will
  203. be taken as the value of the progress bar. If it is a list, the first
  204. item in the list must be the value of the progress bar, and the second
  205. item must be a text string with will be used to update the status text.
  206. @param text: another way to specify the optional text with which to
  207. update the status string.
  208. @param max: change the maximum value of the gauge if given
  209. """
  210. if isinstance(value, list):
  211. value, text = value
  212. do_yield = False
  213. update = False
  214. if self.gauge_delay > 0:
  215. self.gauge_refresh_count += 1
  216. if time.time() > self.gauge_show_time:
  217. if not self.gauge_shown:
  218. self._showProgress(max)
  219. self.gauge_shown = True
  220. self.gauge_refresh_trigger = self.gauge_refresh_count
  221. if self.gauge_refresh_count >= self.gauge_refresh_trigger:
  222. self.gauge_refresh_count = 0
  223. do_yield = True
  224. update = True
  225. else:
  226. update = True
  227. if update and self.parent.info == self:
  228. self.setProgressPosition(value, text, max)
  229. if do_yield:
  230. if self.disable_during_progress:
  231. wx.SafeYield(onlyIfNeeded=True)
  232. else:
  233. wx.GetApp().Yield(True)
  234. def isCancelled(self):
  235. return self.cancelled
  236. def isInProgress(self):
  237. return bool(self.overlays)
  238. def stopProgress(self, text="Completed.", force_text=True):
  239. if self.cancelled:
  240. self.setText("Cancelled.")
  241. elif self.gauge_shown or force_text:
  242. self.setText(text)
  243. self.overlays = []
  244. Publisher().unsubscribe(self.updateMessage)
  245. self.message = None
  246. if self.parent.info == self:
  247. self.parent.setWidths()
  248. def updateMessage(self, msg):
  249. value = msg.data
  250. wx.CallAfter(self.updateProgress, value)
  251. class ModularStatusBar(wx.StatusBar):
  252. def __init__(self, parent, widths=[-1, 150]):
  253. wx.StatusBar.__init__(self, parent, -1)
  254. if wx.Platform == '__WXGTK__':
  255. self.spacing = 3
  256. else:
  257. self.spacing = 0
  258. self.controls = {}
  259. self.info = None
  260. self.default_info = ModularStatusBarInfo(self, widths)
  261. self.info = self.default_info
  262. self.gauge = wx.Gauge(self, -1, 100)
  263. self.gauge.Hide()
  264. self.cancel = wx.Button(self, -1, _("Cancel"))
  265. self.cancel.Hide()
  266. self.Bind(wx.EVT_BUTTON, self.OnCancel, self.cancel)
  267. self.setWidths()
  268. self.sizeChanged = False
  269. self.Bind(wx.EVT_SIZE, self.OnSize)
  270. self.Bind(wx.EVT_IDLE, self.OnIdle)
  271. parent.SetStatusBar(self)
  272. self.Show()
  273. def changeInfo(self, info=None):
  274. if info:
  275. self.info = info
  276. else:
  277. self.info = self.default_info
  278. self.info.resetProgress()
  279. def setWidths(self):
  280. self.widths = [i for i in self.info.widths]
  281. for widget in self.info.active_controls:
  282. self.widths.append(widget.GetSizeTuple()[0] + 2*self.spacing)
  283. self.widths.append(16 + 2*self.spacing) # leave space for the resizer
  284. self.SetFieldsCount(len(self.widths))
  285. self.SetStatusWidths(self.widths)
  286. for i in range(len(self.widths)):
  287. if i < len(self.info.widths):
  288. self.SetStatusText(self.info.text[i], i)
  289. else:
  290. self.SetStatusText(' ', i)
  291. self.Reposition()
  292. def getIcon(self, bmp, tooltip=None):
  293. if isinstance(bmp,str):
  294. bmp = getIconBitmap(bmp)
  295. if bmp not in self.controls:
  296. b = StatusBarButton(self, -1, bmp, style=wx.BORDER_NONE, pos=(9000,9000))
  297. b.Hide()
  298. self.controls[bmp] = b
  299. btn = self.controls[bmp]
  300. if tooltip:
  301. btn.SetToolTipString(tooltip)
  302. return btn
  303. def OnSize(self, evt):
  304. self.Reposition() # for normal size events
  305. # Set a flag so the idle time handler will also do the repositioning.
  306. # It is done this way to get around a buglet where GetFieldRect is not
  307. # accurate during the EVT_SIZE resulting from a frame maximize.
  308. self.sizeChanged = True
  309. def OnIdle(self, evt):
  310. if self.sizeChanged:
  311. self.Reposition()
  312. # reposition the checkbox
  313. def Reposition(self):
  314. shown = {}
  315. if self.info.active_controls:
  316. field = len(self.info.widths)
  317. for widget in self.info.active_controls:
  318. rect = self.GetFieldRect(field)
  319. #dprint(rect)
  320. size = widget.GetSize()
  321. #dprint(size)
  322. xoffset = (rect.width - size.width)/2
  323. yoffset = (rect.height - size.height)/2
  324. #dprint((xoffset, yoffset))
  325. widget.SetPosition((rect.x + xoffset,
  326. rect.y + yoffset + self.spacing))
  327. #widget.SetSize((rect.width-4, rect.height-4))
  328. shown[widget] = True
  329. field += 1
  330. for widget in self.controls.values():
  331. state = widget in shown
  332. widget.Show(state)
  333. shown = {}
  334. if self.info.overlays:
  335. rect = self.GetFieldRect(0)
  336. x = rect.width
  337. overlays = [a for a in self.info.overlays]
  338. overlays.reverse()
  339. shown = {}
  340. for widget, width in overlays:
  341. x -= width
  342. widget.SetPosition((x, rect.y))
  343. widget.SetSize((width, rect.height))
  344. #print("x=%d width=%d widget=%s" % (x, width, widget))
  345. shown[widget] = True
  346. for widget in [self.gauge, self.cancel]:
  347. state = widget in shown
  348. widget.Show(state)
  349. self.sizeChanged = False
  350. def OnCancel(self, evt):
  351. self.info.cancelled = True
  352. class FontBrowseButton(wx.Panel):
  353. """Simple panel and button to choose and display a new font.
  354. Borrowed from the wxPython demo.
  355. """
  356. def __init__(self, parent, font=None):
  357. wx.Panel.__init__(self, parent, -1)
  358. btn = wx.Button(self, -1, "Select Font")
  359. self.Bind(wx.EVT_BUTTON, self.OnSelectFont, btn)
  360. self.sampleText = wx.TextCtrl(self, -1, size=(150, -1), style=wx.TE_CENTRE)
  361. self.sampleText.SetEditable(False)
  362. self.sampleText.SetBackgroundColour(wx.WHITE)
  363. if font is None:
  364. self.curFont = self.sampleText.GetFont()
  365. else:
  366. self.curFont = font
  367. self.curClr = wx.BLACK
  368. sizer = wx.BoxSizer(wx.HORIZONTAL)
  369. sizer.Add(self.sampleText, 1, wx.EXPAND)
  370. sizer.Add(btn, 0, wx.EXPAND)
  371. self.SetSizer(sizer)
  372. self.UpdateUI()
  373. def UpdateUI(self):
  374. self.sampleText.SetFont(self.curFont)
  375. self.sampleText.SetForegroundColour(self.curClr)
  376. self.sampleText.SetValue("%s %s" % (self.curFont.GetFaceName(), self.curFont.GetPointSize()))
  377. self.Layout()
  378. def OnSelectFont(self, evt):
  379. data = wx.FontData()
  380. data.EnableEffects(True)
  381. data.SetColour(self.curClr) # set colour
  382. data.SetInitialFont(self.curFont)
  383. dlg = wx.FontDialog(self, data)
  384. if dlg.ShowModal() == wx.ID_OK:
  385. data = dlg.GetFontData()
  386. font = data.GetChosenFont()
  387. colour = data.GetColour()
  388. # print('You selected: "%s", %d points, color %s\n' %
  389. # (font.GetFaceName(), font.GetPointSize(),
  390. # colour.Get()))
  391. self.curFont = font
  392. self.curClr = colour
  393. self.UpdateUI()
  394. # Don't destroy the dialog until you get everything you need from the
  395. # dialog!
  396. dlg.Destroy()
  397. def getFont(self):
  398. return self.curFont
  399. def setFont(self, font):
  400. if font is not None:
  401. self.curFont = font
  402. self.UpdateUI()
  403. class FileBrowseButton2(FileBrowseButton):
  404. """Small enhancements to FileBrowseButton"""
  405. def createDialog( self, parent, id, pos, size, style, *args, **kwargs):
  406. """Setup the graphic representation of the dialog"""
  407. wx.Panel.__init__ (self, parent, id, pos, size, style, *args, **kwargs)
  408. self.SetMinSize(size) # play nice with sizers
  409. box = wx.BoxSizer(wx.HORIZONTAL)
  410. self.label = self.createLabel( )
  411. #box.Add( self.label, 0, wx.CENTER )
  412. self.textControl = self.createTextControl()
  413. box.Add( self.textControl, 1, wx.LEFT|wx.CENTER, 0)
  414. self.browseButton = self.createBrowseButton()
  415. box.Add( self.browseButton, 0, wx.LEFT|wx.CENTER, 5)
  416. # add a border around the whole thing and resize the panel to fit
  417. outsidebox = wx.BoxSizer(wx.VERTICAL)
  418. outsidebox.Add(box, 1, wx.EXPAND|wx.ALL, 0)
  419. outsidebox.Fit(self)
  420. self.SetAutoLayout(True)
  421. self.SetSizer( outsidebox )
  422. self.Layout()
  423. if type( size ) == types.TupleType:
  424. size = apply( wx.Size, size)
  425. self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
  426. def SetToolTipString(self, text):
  427. #dprint(text)
  428. self.textControl.SetToolTipString(text)
  429. def IsEnabled(self):
  430. """Make IsEnabled work by returning the enabled state of the
  431. text control
  432. """
  433. # FileBrowseButton never sets the enabled state of the panel
  434. # itself, so it always returns True. Make it return the state
  435. # of the text control, which should indicate the real enabled state.
  436. return self.textControl.IsEnabled()
  437. def OnBrowse(self, event=None):
  438. """Replacing the default action because it doesn't check for bad
  439. directories.
  440. """
  441. current = self.GetValue()
  442. directory = os.path.split(current)
  443. if os.path.isdir( current):
  444. directory = current
  445. current = ''
  446. elif directory and os.path.isdir( directory[0] ):
  447. current = directory[1]
  448. directory = directory [0]
  449. else:
  450. current = ''
  451. directory = self.startDirectory
  452. dprint(current)
  453. dprint(directory)
  454. dlg = wx.FileDialog(self, self.dialogTitle, directory, current,
  455. self.fileMask, self.fileMode)
  456. if dlg.ShowModal() == wx.ID_OK:
  457. self.SetValue(dlg.GetPath())
  458. dlg.Destroy()
  459. def SetValue (self, value, callBack=1):
  460. """set current value of text control"""
  461. if callBack:
  462. self.textControl.SetValue(value)
  463. else:
  464. self.textControl.ChangeValue(value)
  465. class DirBrowseButton2(FileBrowseButton2):
  466. """Update to dir browse button to browse to the currently set
  467. directory instead of always using the initial directory.
  468. """
  469. def createDialog(self, *args, **kwargs):
  470. """Automatically hide the label because it's not used here"""
  471. FileBrowseButton2.createDialog(self, *args, **kwargs)
  472. self.dialogClass = wx.DirDialog
  473. self.newDirectory = False
  474. def OnBrowse(self, ev = None):
  475. current = self.GetValue()
  476. directory = os.path.split(current)
  477. if os.path.isdir( current):
  478. directory = current
  479. current = ''
  480. elif directory and os.path.isdir( directory[0] ):
  481. current = directory[1]
  482. directory = directory [0]
  483. else:
  484. directory = self.startDirectory
  485. style=0
  486. if not self.newDirectory:
  487. style |= wx.DD_DIR_MUST_EXIST
  488. dialog = self.dialogClass(self,
  489. message = self.dialogTitle,
  490. defaultPath = directory,
  491. style = style)
  492. if dialog.ShowModal() == wx.ID_OK:
  493. self.SetValue(dialog.GetPath())
  494. dialog.Destroy()
  495. class CredentialsDialog(wx.Dialog):
  496. def __init__(self, parent, title="Authentication Required", url=None, realm=None, username=None):
  497. wx.Dialog.__init__(self, parent, -1, title,
  498. size=wx.DefaultSize, pos=wx.DefaultPosition,
  499. style=wx.DEFAULT_DIALOG_STYLE)
  500. sizer = wx.BoxSizer(wx.VERTICAL)
  501. message = ""
  502. if url:
  503. message += "A username and password are being requested by %s\n" % url
  504. if realm:
  505. message += "The site says: \"%s\"" % realm
  506. label = wx.StaticText(self, -1, message)
  507. sizer.Add(label, 0, flag=wx.ALIGN_CENTRE|wx.ALL)
  508. bag = wx.GridBagSizer(5, 5)
  509. bag.AddGrowableCol(1)
  510. label = wx.StaticText(self, label=_("Username") + u":")
  511. bag.Add(label, (1, 0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL|wx.ALL)
  512. self.username = wx.TextCtrl(self, -1)
  513. bag.Add(self.username, (1, 1), flag=wx.ALIGN_LEFT|wx.ALL|wx.EXPAND)
  514. label = wx.StaticText(self, label=_("Password") + u":")
  515. bag.Add(label, (2, 0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL|wx.ALL)
  516. self.password = wx.TextCtrl(self, -1, style=wx.TE_PASSWORD)
  517. bag.Add(self.password, (2, 1), flag=wx.ALIGN_LEFT|wx.ALL|wx.EXPAND)
  518. sizer.Add(bag, 1, wx.EXPAND)
  519. btnsizer = wx.StdDialogButtonSizer()
  520. btn = wx.Button(self, wx.ID_OK)
  521. btn.SetDefault()
  522. btnsizer.AddButton(btn)
  523. btn = wx.Button(self, wx.ID_CANCEL)
  524. btnsizer.AddButton(btn)
  525. btnsizer.Realize()
  526. sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
  527. self.SetSizer(sizer)
  528. sizer.Fit(self)
  529. self.Layout()
  530. if username:
  531. self.username.SetValue(username)
  532. self.password.SetFocus()
  533. else:
  534. self.username.SetFocus()
  535. def getUsername(self):
  536. return self.username.GetValue()
  537. def getPassword(self):
  538. return self.password.GetValue()
  539. if __name__ == "__main__":
  540. class TestFrame(wx.Frame):
  541. def __init__(self, parent):
  542. wx.Frame.__init__(self, parent, -1, "Status Bar Test", wx.DefaultPosition, wx.DefaultSize)
  543. self.statusbar = ModularStatusBar(self)
  544. sizer = wx.BoxSizer(wx.VERTICAL)
  545. font = FontBrowseButton(self)
  546. sizer.Add(font, 0, wx.EXPAND)
  547. button1 = wx.Button(self, -1, "Statusbar 1")
  548. button1.Bind(wx.EVT_BUTTON, self.setStatus1)
  549. sizer.Add(button1, 0, wx.EXPAND)
  550. self.status_info1 = self.statusbar.info
  551. self.status_info1.addIcon("icons/windows.png", "DOS/Windows line endings")
  552. self.status_info1.addIcon("icons/apple.png", "Old-style Apple line endings")
  553. self.status_info1.addIcon("icons/tux.png", "Unix line endings")
  554. self.status_info1.setText("Status Bar 1")
  555. button2 = wx.Button(self, -1, "Statusbar 2")
  556. button2.Bind(wx.EVT_BUTTON, self.setStatus2)
  557. sizer.Add(button2, 0, wx.EXPAND)
  558. self.status_info2 = ModularStatusBarInfo(self.statusbar, [50, -1])
  559. self.status_info2.setText("Status Bar 2")
  560. self.status_info2.setText("blah", 1)
  561. button3 = wx.Button(self, -1, "Statusbar 3")
  562. button3.Bind(wx.EVT_BUTTON, self.setStatus3)
  563. sizer.Add(button3, 0, wx.EXPAND)
  564. self.status_info3 = ModularStatusBarInfo(self.statusbar, [150, -1])
  565. self.status_info3.addIcon("icons/tux.png", "Unix line endings")
  566. self.status_info3.addIcon("icons/apple.png", "Old-style Apple line endings")
  567. self.status_info3.setText("Status Bar 3")
  568. self.status_info3.startProgress("Stuff!")
  569. self.count3 = 0
  570. button4 = wx.Button(self, -1, "Statusbar 4")
  571. button4.Bind(wx.EVT_BUTTON, self.setStatus4)
  572. sizer.Add(button4, 0, wx.EXPAND)
  573. self.status_info4 = ModularStatusBarInfo(self.statusbar, [-1])
  574. self.status_info4.addIcon("icons/apple.png", "Old-style Apple line endings")
  575. self.status_info4.setText("Status Bar 4")
  576. self.status_info4.startProgress("Stuff!", cancel=True)
  577. self.count4 = 0
  578. self.timer = wx.Timer(self)
  579. self.Bind(wx.EVT_TIMER, self.OnTimer)
  580. self.timer.Start(1000/10)
  581. login = wx.Button(self, -1, "Show Login")
  582. login.Bind(wx.EVT_BUTTON, self.showLogin)
  583. sizer.Add(login, 0, wx.EXPAND)
  584. self.SetAutoLayout(1)
  585. self.SetSizer(sizer)
  586. self.Show(1)
  587. def OnTimer(self, evt):
  588. self.count3 = (self.count3 + 1) % 100
  589. self.status_info3.updateProgress(self.count3)
  590. if self.status_info4.isInProgress():
  591. if self.status_info4.isCancelled():
  592. self.status_info4.stopProgress()
  593. else:
  594. self.count4 = (self.count4 + 3) % 100
  595. self.status_info4.updateProgress(self.count4)
  596. def setStatus1(self, evt):
  597. print("status 1")
  598. self.statusbar.changeInfo(self.status_info1)
  599. evt.Skip()
  600. def setStatus2(self, evt):
  601. print("status 2")
  602. self.statusbar.changeInfo(self.status_info2)
  603. evt.Skip()
  604. def setStatus3(self, evt):
  605. print("status 3")
  606. self.statusbar.changeInfo(self.status_info3)
  607. evt.Skip()
  608. def setStatus4(self, evt):
  609. print("status 4")
  610. self.statusbar.changeInfo(self.status_info4)
  611. evt.Skip()
  612. def showLogin(self, evt):
  613. wx.CallAfter(self.showLoginCallback)
  614. def showLoginCallback(self):
  615. dlg = CredentialsDialog(self, url="http://some.web.site", realm="Files and Stuff")
  616. ret = dlg.ShowModal()
  617. if ret == wx.ID_OK:
  618. dprint("username=%s, password=%s" % (dlg.getUsername(), dlg.getPassword()))
  619. dlg.Destroy()
  620. app = wx.PySimpleApp()
  621. frame = TestFrame(None)
  622. app.MainLoop()