def hireWorker(self, argtuple=(), argdict={}): # Create and start the appropriate kind of Worker to perform # the menu item. If menuItem is threadable create a threaded # Worker and launch the thread. There are different kinds of # threaded Workers. getThreadedWorker returns the appropriate # one. # It is tempting to put "if parallel_enable.enabled():..." but # threadable can carry more options than just # PARALLEL_THREADABLE and PARALLEL_UNTHREADABLE. if (self.threadable is PARALLEL_UNTHREADABLE and parallel_enable.enabled()): workerclass = worker.ParallelWorker elif (self.threadable is PARALLEL_THREADABLE and parallel_enable.enabled()): if thread_enable.enabled(): workerclass = worker.getThreadedParallelWorker else: workerclass = worker.ParallelWorker elif (self.threadable is UNTHREADABLE or not thread_enable.enabled() or (self.threadable is THREADABLE_GUI and not guitop.top()) or (self.threadable is THREADABLE_TEXT and guitop.top())): workerclass = worker.NonThreadedWorker else: # worker.getThreadedWorker returns a # TextThreadedWorker in text mode, and either a # ThreadedWorker of GUIThreadedWorkerBlock in GUI # mode. workerclass = worker.getThreadedWorker the_worker = workerclass(self, argtuple, argdict) garbage.collect() # Launch the thread (and wait for it to finish if in text # mode). the_worker.start()
def deleteLayer_gui(self, menuitem): if self.selectedLayer is None: guitop.top().message_out('No layer is selected!\n') else: self.suppressSelectionSignals() try: self.menu.Layer.Delete(n=self.layerID(self.selectedLayer)) finally: self.allowSelectionSignals()
def __init__(self, pixelinfotoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Pixel Info", pixelinfotoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) self.table = gtk.Table(rows=3, columns=2) mainbox.pack_start(self.table, expand=0, fill=0) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 0,1, xpadding=5, xoptions=gtk.FILL) self.xtext = gtk.Entry() gtklogger.setWidgetName(self.xtext, "X") self.xtext.set_size_request(10*guitop.top().digitsize, -1) self.table.attach(self.xtext, 1,2, 0,1, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) label = gtk.Label('y=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 1,2, xpadding=5, xoptions=gtk.FILL) self.ytext = gtk.Entry() gtklogger.setWidgetName(self.ytext, "Y") self.ytext.set_size_request(10*guitop.top().digitsize, -1) self.table.attach(self.ytext, 1,2, 1,2, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) self.xtsignal = gtklogger.connect(self.xtext, 'changed', self.pointChanged) self.ytsignal = gtklogger.connect(self.ytext, 'changed', self.pointChanged) box = gtk.HBox(homogeneous=True, spacing=2) self.updatebutton = gtkutils.StockButton(gtk.STOCK_REFRESH, 'Update') box.pack_start(self.updatebutton, expand=1, fill=1) gtklogger.setWidgetName(self.updatebutton, "Update") gtklogger.connect(self.updatebutton, 'clicked', self.updateButtonCB) self.clearbutton = gtkutils.StockButton(gtk.STOCK_CLEAR, 'Clear') box.pack_start(self.clearbutton, expand=1, fill=1) gtklogger.setWidgetName(self.clearbutton, "Clear") gtklogger.connect(self.clearbutton, 'clicked', self.clearButtonCB) self.table.attach(box, 0,2, 2,3, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) self.updatebutton.set_sensitive(0) self.clearbutton.set_sensitive(0) self.buildGUI() self.sbcallbacks = [ switchboard.requestCallbackMain(pixelinfotoolbox, self.update), switchboard.requestCallbackMain('new pixelinfo plugin', self.buildGUI), switchboard.requestCallbackMain((self.gfxwindow(), 'layers changed'), self.update) ]
def __init__(self, toolbox, table, row): debug.mainthreadTest() PixelInfoPlugIn.__init__(self, toolbox) label = gtk.Label('microstructure=') label.set_alignment(1.0, 0.5) table.attach(label, 0, 1, row, row + 1, xpadding=5, xoptions=gtk.FILL) self.microtext = gtk.Entry() gtklogger.setWidgetName(self.microtext, 'MSText') self.microtext.set_size_request(12 * guitop.top().charsize, -1) self.microtext.set_editable(0) table.attach(self.microtext, 1, 2, row, row + 1, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) label = gtk.Label('pixel groups=') label.set_alignment(1.0, 0.5) table.attach(label, 0, 1, row + 1, row + 2, xpadding=5, xoptions=gtk.FILL) self.grouplist = gtk.TextView() self.grouplist.set_size_request(12 * guitop.top().charsize, -1) self.grouplist.set_editable(False) self.grouplist.set_cursor_visible(False) self.grouplist.set_wrap_mode(gtk.WRAP_WORD) gtklogger.setWidgetName(self.grouplist, 'Group view') scroll = gtk.ScrolledWindow() gtklogger.logScrollBars(scroll, "MSScroll") scroll.set_shadow_type(gtk.SHADOW_IN) scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.add(self.grouplist) table.attach(scroll, 1, 2, row + 1, row + 2, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) self.sbcallbacks = [ switchboard.requestCallbackMain('changed pixel group', self.grpchanged), switchboard.requestCallbackMain('changed pixel groups', self.grpschngd), switchboard.requestCallbackMain('destroy pixel group', self.grpdestroy), switchboard.requestCallbackMain('renamed pixel group', self.grprenamed) ]
def entrymaster(self, column, row, editable=0): debug.mainthreadTest() entry = gtk.Entry() entry.set_size_request(13*guitop.top().digitsize, -1) entry.set_editable(editable) self.table.attach(entry, column[0],column[1], row[0],row[1], xpadding=xpadding, xoptions=xoptions) return entry
def copyinitCB(self, button): # gtk callback, copy field initializer menuitem = meshmenu.Copy_Field_Initializers targetparam = menuitem.get_arg("target") targetparam.set(self.currentFullMeshName()) if parameterwidgets.getParameters(targetparam, parentwindow=guitop.top().gtk, title="Select a target Mesh"): menuitem.callWithDefaults(source=self.currentFullMeshName())
def entrymaster(self, column, row, editable=0): debug.mainthreadTest() entry = gtk.Entry() entry.set_size_request(12*guitop.top().digitsize, -1) entry.set_editable(editable) self.table.attach(entry, column[0],column[1], row[0],row[1], xpadding=xpadding, xoptions=gtk.EXPAND|gtk.FILL) return entry
def copyinitCB(self, button): # gtk callback, copy field initializers menuitem = meshmenu.Copy_Field_Initializers targetparam = menuitem.get_arg("target") targetparam.set(self.currentFullMeshName()) if parameterwidgets.getParameters(targetparam, parentwindow=guitop.top().gtk, title="Select a target Mesh"): menuitem.callWithDefaults(source=self.currentFullMeshName())
def __init__(self, param, scope=None, name=None, compact=False): GenericWidget.__init__(self, param=param, scope=scope, name=name, compact=compact) if compact: self.gtk.set_size_request(8 * guitop.top().digitsize, -1)
def __init__(self, param, scope=None, name=None): debug.mainthreadTest() widget = gtk.Entry() widget.set_size_request(10 * guitop.top().charsize, -1) ParameterWidget.__init__(self, widget, scope=scope, name=name) self.signal = gtklogger.connect(widget, 'changed', self.changedCB) self.set_value(param.value) self.widgetChanged(self.validValue(param.value), interactive=0)
def __init__(self, param, scope=None, name=None): debug.mainthreadTest() widget = gtk.Entry() widget.set_size_request(10*guitop.top().charsize, -1) ParameterWidget.__init__(self, widget, scope=scope, name=name) self.signal = gtklogger.connect(widget, 'changed', self.changedCB) self.set_value(param.value) self.widgetChanged(self.validValue(param.value), interactive=0)
def newOutputCB(self, gtkbutton): # Create a new scheduled output menuitem = outputmenu.New params = filter(lambda a: a.name != 'mesh', menuitem.params) if parameterwidgets.getParameters(title='Define a new Output', scope=self, parentwindow=guitop.top().gtk, *params): menuitem.callWithDefaults(mesh=self.currentFullMeshName())
def __init__(self, value=None, vmin=0, vmax=1, step=0.01, callback=None, clipperclass=None, name=None, immediate=True): # "callback" is called when the user moves the slider. If # immediate==True, then the callback will be called when any # character is typed in the Entry. If it's false, the # callback won't be called until the entry loses focus. debug.mainthreadTest() self.immediate = immediate self.gtk = gtk.HPaned() if value is None: value = vmin self.clipperclass = clipperclass or DefaultClipper self.clipper = self.clipperclass(vmin, vmax) if name is not None: gtklogger.setWidgetName(self.gtk, name) self.adjustment = gtk.Adjustment(value=value, lower=vmin, upper=vmax, step_incr=step, page_incr=step) self.slider = gtk.HScale(self.adjustment) gtklogger.setWidgetName(self.slider, "slider") gtklogger.adoptGObject(self.adjustment, self.slider, access_method=self.slider.get_adjustment) self.slider.set_size_request(100, -1) self.gtk.pack1(self.slider, resize=True, shrink=True) self.slider.set_draw_value(False) # we'll display the value ourselves self.adjustmentsignal = gtklogger.connect(self.adjustment, 'value-changed', self.text_from_slider) self.entry = gtk.Entry() gtklogger.setWidgetName(self.entry, "entry") self.gtk.pack2(self.entry, resize=True, shrink=True) # Make sure that the Entry is big enough to hold the min and # max values, or at least 8 digits. width = max(len( ` vmin `), len( ` vmax `), 8) self.entry.set_size_request(width * guitop.top().digitsize, -1) self.entrysignal = gtklogger.connect(self.entry, 'changed', self.entry_changed) self.set_value(value) self.callback = callback self.changed = False gtklogger.connect(self.entry, 'activate', self.slider_from_text) gtklogger.connect(self.entry, 'focus-out-event', self.entry_lost_focus)
def renameCB(self, gtkbutton): menuitem = outputmenu.Rename nameparam = menuitem.get_arg('name') name = self.currentOutputName() nameparam.set(name) if parameterwidgets.getParameters(nameparam, title='Rename output "%s"' % name, scope=self, parentwindow=guitop.top().gtk): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), output=self.currentOutputName())
def renameCB(self, gtkbutton): menuitem = outputmenu.Rename nameparam = menuitem.get_arg('name') name = self.currentOutputName() nameparam.set(name) if parameterwidgets.getParameters(nameparam, title='Rename output "%s"'%name, scope=self, parentwindow=guitop.top().gtk): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), output=self.currentOutputName())
def setSolverCB(self, *args): # gtk callback menuitem = subpmenu.Set_Solver subp = self.currentSubProblemContext() mode_arg = menuitem.get_arg('solver_mode') mode_arg.set(subp.solver_mode) if parameterwidgets.getParameters(mode_arg, title='Specify Solver', parentwindow=guitop.top().gtk, scope=self): menuitem.callWithDefaults( subproblem=self.currentFullSubProblemName())
def copySchedCB(self, gtkbutton): menuitem = outputmenu.Schedule.Copy targetmeshparam = menuitem.get_arg('targetmesh') targetmeshparam.set(self.currentFullMeshName()) targetparam = menuitem.get_arg('target') if parameterwidgets.getParameters(targetmeshparam, targetparam, parentwindow=guitop.top().gtk, title="Copy an Output Schedule", scope=self): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), source=self.currentOutputName())
def copyOutputCB(self, gtkbutton): menuitem = outputmenu.Copy output = self.currentOutput() targetmeshparam = menuitem.get_arg('targetmesh') targetmeshparam.set(self.currentFullMeshName()) if parameterwidgets.getParameters(targetmeshparam, menuitem.get_arg('copy'), scope=self, title="Copy an Output", parentwindow=guitop.top().gtk): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), source=self.currentOutputName())
def setDestinationCB(self, *args): assert self.currentOutput() is not None menuitem = outputmenu.Destination.Set destparam = menuitem.get_arg('destination') if self.currentOutput().destination is not None: destparam.set(self.currentOutput().destination) if parameterwidgets.getParameters(destparam, parentwindow=guitop.top().gtk, title='Set an Output Destination', scope=self): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), output=self.currentOutputName())
def __init__(self, question, *answers, **kwargs): debug.mainthreadTest() if len(answers) == 0: raise ooferror.ErrSetupError( "Questioner must have at least one possible answer.") self.answers = answers self.gtk = gtklogger.Dialog(parent=guitop.top().gtk) gtklogger.newTopLevelWidget(self.gtk, "Questioner") hbox = gtk.HBox() self.gtk.vbox.pack_start(hbox, padding=15) hbox.pack_start(gtk.Label(question), padding=15) self.defaultbutton = None try: self.default = kwargs['default'] except KeyError: self.default = None else: if not self.default in answers: self.answers = (self.default, ) + answers self.answerdict = {} count = 1 for answer in self.answers: #TODO:Replace the try except block with this #stock = answer["stock"] #choice = answer["choice"] #icon = gtk.stock_lookup(stock) #if icon is None: # debug.fmsg('no gtk stock icon for id: ', stock) # self.gtk.add_button(choice, count) #else: # button = self.gtk.add_button(icon, count) # label = gtkutils.findChild(gtk.Label, button) # label.set_text(choice) #if answer["stock"] == self.default["stock"]: # self.gtk.set_default_response(count) try: stock = _stock[answer] button = self.gtk.add_button(stock, count) # Replace the label on the stock button with the answer text. label = gtkutils.findChild(gtk.Label, button) label.set_text(answer) except KeyError: debug.fmsg('no stock icon for', answer) self.gtk.add_button(answer, count) self.answerdict[count] = answer if answer == self.default: self.gtk.set_default_response(count) count += 1 hbox.show_all()
def __init__(self, toolbox, table, row): debug.mainthreadTest() PixelInfoPlugIn.__init__(self, toolbox) label = gtk.Label('microstructure=') label.set_alignment(1.0, 0.5) table.attach(label, 0,1, row,row+1, xpadding=5, xoptions=gtk.FILL) self.microtext = gtk.Entry() gtklogger.setWidgetName(self.microtext,'MSText') self.microtext.set_size_request(12*guitop.top().charsize, -1) self.microtext.set_editable(0) table.attach(self.microtext, 1,2, row,row+1, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) label = gtk.Label('pixel groups=') label.set_alignment(1.0, 0.5) table.attach(label, 0,1, row+1,row+2, xpadding=5, xoptions=gtk.FILL) self.grouplist = gtk.TextView() self.grouplist.set_size_request(12*guitop.top().charsize, -1) self.grouplist.set_editable(False) self.grouplist.set_cursor_visible(False) self.grouplist.set_wrap_mode(gtk.WRAP_WORD) gtklogger.setWidgetName(self.grouplist, 'Group view') scroll = gtk.ScrolledWindow() gtklogger.logScrollBars(scroll, "MSScroll") scroll.set_shadow_type(gtk.SHADOW_IN) scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.add(self.grouplist) table.attach(scroll, 1,2, row+1,row+2, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) self.sbcallbacks = [ switchboard.requestCallbackMain('changed pixel group', self.grpchanged), switchboard.requestCallbackMain('changed pixel groups', self.grpschngd), switchboard.requestCallbackMain('destroy pixel group', self.grpdestroy), switchboard.requestCallbackMain('renamed pixel group', self.grprenamed) ]
def editOutputCB(self, *args): menuitem = outputmenu.Edit output = self.currentOutput() newoutputparam = menuitem.get_arg('new_output') newoutputparam.set(output) params = filter(lambda a: a.name not in ('mesh', 'output'), menuitem.params) if parameterwidgets.getParameters(title='Redefine an Output', scope=self, parentwindow=guitop.top().gtk, *params): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), output=self.currentOutputName())
def _append(self, type, *args): message = string.join([str(x) for x in args], ' ') MessageManager.lock.acquire() try: if debug.debug() and type!="Log" and guitop.top(): print message self.message_list.append( (message, type) ) if self.flag_dict[type]: self._write(message) finally: MessageManager.lock.release() switchboard.notify( "write message", (message, type) ) return message
def setSchedCB(self, *args): menuitem = outputmenu.Schedule.Set schedparam = menuitem.get_arg('schedule') schedtypeparam = menuitem.get_arg('scheduletype') if self.currentOutput().schedule is not None: schedparam.set(self.currentOutput().schedule) schedtypeparam.set(self.currentOutput().scheduleType) if parameterwidgets.getParameters(schedtypeparam, schedparam, parentwindow=guitop.top().gtk, title='Set an Output Schedule', scope=self): menuitem.callWithDefaults(mesh=self.currentFullMeshName(), output=self.currentOutputName())
def _append(self, type, *args): message = ' '.join([str(x) for x in args]) self.lock.acquire() try: if debug.debug() and type!="Log" and guitop.top(): print message self.message_list.append( (message, type) ) if self.flag_dict[type]: self._write(message) finally: self.lock.release() switchboard.notify( "write message", (message, type) ) return message
def hireWorker(self, argtuple=(), argdict={}, workerclass=None): # Create and start the appropriate kind of Worker to perform # the menu item. If menuItem is threadable create a threaded # Worker and launch the thread. There are different kinds of # threaded Workers. getThreadedWorker returns the appropriate # one. if workerclass is None: # TODO: Is the workerclass arg ever not None? # It is tempting to put "if parallel_enable.enabled():..." but # threadable can carry more options than just # PARALLEL_THREADABLE and PARALLEL_UNTHREADABLE. if (self.threadable is PARALLEL_UNTHREADABLE and parallel_enable.enabled()): workerclass = worker.ParallelWorker elif (self.threadable is PARALLEL_THREADABLE and parallel_enable.enabled()): if thread_enable.enabled(): workerclass = worker.getThreadedParallelWorker else: workerclass = worker.ParallelWorker elif (self.threadable is UNTHREADABLE or not thread_enable.enabled() or (self.threadable is THREADABLE_GUI and not guitop.top()) or (self.threadable is THREADABLE_TEXT and guitop.top()) ): workerclass = worker.NonThreadedWorker else: # worker.getThreadedWorker returns a # TextThreadedWorker in text mode, and either a # ThreadedWorker of GUIThreadedWorkerBlock in GUI # mode. workerclass = worker.getThreadedWorker the_worker = workerclass(self, argtuple, argdict) garbage.collect() # Launch the thread (and wait for it to finish if in text # mode). the_worker.start()
def __init__(self, toolbox, table, row): debug.mainthreadTest() pixelinfoplugin.PixelInfoPlugIn.__init__(self, toolbox) label=gtk.Label('material=') label.set_alignment(1.0, 0.5) table.attach(label, 0,1, row,row+1, xpadding=5, xoptions=gtk.FILL) self.materialtext = gtk.Entry() gtklogger.setWidgetName(self.materialtext, 'material') self.materialtext.set_size_request(12*guitop.top().charsize, -1) self.materialtext.set_editable(0) table.attach(self.materialtext, 1,2, row,row+1, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) self.sbcb = switchboard.requestCallbackMain( 'materials changed in microstructure', self.matchanged)
def __init__(self,label,rows,cols,value=None,scope=None,name=None): debug.mainthreadTest() frame = gtk.Frame() self.table = gtk.Table(rows=rows+1, columns=cols+1) frame.add(self.table) parameterwidgets.ParameterWidget.__init__(self, frame, scope, name) widgetscope.WidgetScope.__init__(self, scope) #scope.addWidget(self) self.rows = rows self.cols = cols self.floats = {} self.sbcallbacks = [] # #self.table = gtk.GtkTable(rows=self.rows+2,cols=self.cols+2) # # Do labels first. for r in range(self.rows): lbl = gtk.Label(' %d ' % (r+1)) lbl.set_alignment(1.0, 0.5) self.table.attach(lbl,0,1,r+1,r+2) for c in range(self.cols): lbl = gtk.Label(`c+1`) self.table.attach(lbl,c+1,c+2,0,1) digitsize = guitop.top().digitsize # Now put the actual floats in. for r in range(self.rows): for c in range(r,self.cols): newfloat = parameterwidgets.FloatWidget( parameter.FloatParameter('dummy',0.0), scope=self, name="%d,%d"%(r,c)) self.sbcallbacks.append( switchboard.requestCallbackMain(newfloat, self.floatChangeCB)) # Also, set the size -- otherwise, the matrix # array gets to be too big. newfloat.gtk.set_size_request(8*digitsize,-1) self.floats[(r,c)] = newfloat try: self.floats[(r,c)].set_value(value[(r,c)]) except: pass self.table.attach(newfloat.gtk,c+1,c+2,r+1,r+2, xoptions=gtk.FILL) self.widgetChanged(1, interactive=0)
def _updatePBdisplayNow(progressid): debug.mainthreadTest() # Don't do anything unless threads are enabled and the gui has # been started. if thread_enable.query() and guitop.top(): prog = progress.findProgressByID(progressid) if prog is not None and not (prog.finished() or prog.stopped()): # Create just one activity viewer. If it's been opened # and closed already, don't reopen it automatically. if not _activityViewerOpened: # The newly created Activity Viewer window # automatically calls installBar for every existing # Progress object, including the one identified by the # argument to this routine. openActivityViewer() else: # The Activity Viewer might have been closed, in which # case activityViewer is None. if activityViewer is not None: activityViewer.addGTKBar(prog)
def __init__(self, question, *answers, **kwargs): debug.mainthreadTest() if len(answers)==0: raise ooferror.ErrSetupError( "Questioner must have at least one possible answer.") self.answers = answers self.gtk = gtklogger.Dialog(parent=guitop.top().gtk) gtklogger.newTopLevelWidget(self.gtk, "Questioner") hbox = gtk.HBox() self.gtk.vbox.pack_start(hbox, padding=15) hbox.pack_start(gtk.Label(question), padding=15) self.defaultbutton = None try: self.default = kwargs['default'] except KeyError: self.default=None else: if not self.default in answers: self.answers = (self.default,)+answers self.answerdict = {} count = 1 for answer in self.answers: try: stock = _stock[answer] button = self.gtk.add_button(stock, count) # Replace the label on the stock button with the answer text. label = gtkutils.findChild(gtk.Label, button) label.set_text(answer) except KeyError: debug.fmsg('no stock icon for', answer) self.gtk.add_button(answer, count) self.answerdict[count] = answer if answer == self.default: self.gtk.set_default_response(count) count += 1 hbox.show_all()
def rebuildFieldTable(self, nfieldrows, listedfields): for entry in self.fieldvalEntries.values(): entry.destroy() for widget in self.fieldvalWidgets: widget.destroy() self.fieldvalEntries.clear() self.fieldvalWidgets.clear() self.table.resize(rows=self.baserows + nfieldrows, columns=3) frow = self.baserows # starting row for a field for fld in listedfields: sep = gtk.HSeparator() self.fieldvalWidgets.add(sep) self.table.attach(sep, 0, 3, frow, frow + 1, xoptions=gtk.FILL) frow += 1 label = gtk.Label(fld.name()) label.set_alignment(1.0, 0.5) self.fieldvalWidgets.add(label) self.table.attach(label, 0, 1, frow, frow + fld.ndof(), xoptions=0) fcomp = fld.iterator(planarity.ALL_INDICES) while not fcomp.end(): row = frow + fcomp.integer() label = gtk.Label(" " + fcomp.shortrepr() + "=") self.fieldvalWidgets.add(label) self.table.attach(label, 1, 2, row, row + 1, xoptions=gtk.FILL) e = gtk.Entry() e.set_size_request(10 * guitop.top().charsize, -1) e.set_editable(False) self.fieldvalEntries[(fld, fcomp.integer())] = e self.table.attach(e, 2, 3, row, row + 1, xoptions=gtk.EXPAND | gtk.FILL) fcomp.next() frow += fld.ndof() # end loop over listedfields self.table.show_all() self.fieldslisted = listedfields
def __init__(self, value=None, vmin=0, vmax=1, step=0.01, callback=None, name=None, immediate=True): # "callback" is called when the user moves the slider. If # immediate==True, then the callback will be called when any # character is typed in the Entry. If it's false, the # callback won't be called until the entry loses focus. debug.mainthreadTest() self.immediate = immediate self.gtk = gtk.HPaned() if value is None: value = vmin if name is not None: gtklogger.setWidgetName(self.gtk, name) self.adjustment = gtk.Adjustment(value=value, lower=vmin, upper=vmax, step_incr=step, page_incr=step) self.slider = gtk.HScale(self.adjustment) gtklogger.setWidgetName(self.slider, "slider") gtklogger.adoptGObject(self.adjustment, self.slider, access_method=self.slider.get_adjustment) self.slider.set_size_request(100, -1) self.gtk.pack1(self.slider, resize=True, shrink=True) self.slider.set_draw_value(False) # we'll display the value ourselves self.adjustmentsignal = gtklogger.connect(self.adjustment, "value-changed", self.text_from_slider) self.entry = gtk.Entry() gtklogger.setWidgetName(self.entry, "entry") self.gtk.pack2(self.entry, resize=True, shrink=True) # Make sure that the Entry is big enough to hold the min and # max values, or at least 8 digits. width = max(len(` vmin `), len(` vmax `), 8) self.entry.set_size_request(width * guitop.top().digitsize, -1) self.entrysignal = gtklogger.connect(self.entry, "changed", self.entry_changed) self.set_value(value) self.callback = callback self.changed = False gtklogger.connect(self.entry, "activate", self.slider_from_text) gtklogger.connect(self.entry, "focus-out-event", self.entry_lost_focus)
def update(self, namelist, helpdict={}): debug.mainthreadTest() # Replace the widget's list of names with the given list. The # original value of self.current_string will be restored if it # still exists in the updated namelist. try: current_index = namelist.index(self.current_string) except ValueError: if len(namelist) > 0: current_index = 0 else: current_index = -1 # no selection self.helpdict = helpdict self.suppress_signals() liststore = self.combobox.get_model() liststore.clear() for name in namelist: liststore.append([name]) self.combobox.set_active(current_index) if current_index >= 0: self.current_string = liststore[current_index][0] else: self.current_string = None self.allow_signals() self.set_tooltip() if self.update_callback: self.update_callback(*(self.gtk, self.current_string) + self.update_callback_args) self.combobox.set_sensitive(len(namelist) > 0) # Make the widget wide enough to fit the longest name it # might display, plus some extra space for the arrow # decoration. if namelist: maxlen = max([len(name) for name in namelist]) self.combobox.set_size_request(30 + maxlen * guitop.top().charsize, -1)
def update(self, namelist, helpdict={}): debug.mainthreadTest() # Replace the widget's list of names with the given list. The # original value of self.current_string will be restored if it # still exists in the updated namelist. try: current_index = namelist.index(self.current_string) except ValueError: if len(namelist) > 0: current_index = 0 else: current_index = -1 # no selection self.helpdict = helpdict self.suppress_signals() liststore = self.combobox.get_model() liststore.clear() for name in namelist: liststore.append([name]) self.combobox.set_active(current_index) if current_index >= 0: self.current_string = liststore[current_index][0] else: self.current_string = None self.allow_signals() self.set_tooltip() if self.update_callback: self.update_callback(*(self.gtk, self.current_string)+ self.update_callback_args) self.combobox.set_sensitive(len(namelist) > 0) # Make the widget wide enough to fit the longest name it # might display, plus some extra space for the arrow # decoration. if namelist: maxlen = max([len(name) for name in namelist]) self.combobox.set_size_request(30+maxlen*guitop.top().charsize, -1)
def __init__(self, name, ordering, tip=None): debug.mainthreadTest() widgetscope.WidgetScope.__init__(self, parent=gui) self.name = name self.ordering = ordering self.tip = tip self.gtk = gtk.Frame() self.gtk.set_shadow_type(gtk.SHADOW_NONE) # Insert the page in the proper spot for i in range(len(pagenames)): if self.ordering < allPages[pagenames[i]].ordering: pagenames.insert(i, name) if guitop.top(): # gui may not be constructed yet! guitop.top().addPage(self, i) break else: # page goes at the end pagenames.append(name) if guitop.top(): # gui may not be constructed yet! guitop.top().addPage(self, len(pagenames)) allPages[name] = self gtklogger.setWidgetName(self.gtk, name + " Page")
def __init__(self, name, ordering, tip=None): debug.mainthreadTest() widgetscope.WidgetScope.__init__(self, parent=gui) self.name = name self.ordering = ordering self.tip = tip self.gtk = gtk.Frame() self.gtk.set_shadow_type(gtk.SHADOW_NONE) # Insert the page in the proper spot for i in range(len(pagenames)): if self.ordering < allPages[pagenames[i]].ordering: pagenames.insert(i, name) if guitop.top(): # gui may not be constructed yet! guitop.top().addPage(self, i) break else: # page goes at the end pagenames.append(name) if guitop.top(): # gui may not be constructed yet! guitop.top().addPage(self, len(pagenames)) allPages[name] = self gtklogger.setWidgetName(self.gtk, name + ' Page')
def __init__(self, pixelinfotoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Pixel Info", pixelinfotoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) self.table = gtk.Table(rows=3, columns=2) mainbox.pack_start(self.table, expand=0, fill=0) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 0, 1, xpadding=5, xoptions=gtk.FILL) self.xtext = gtk.Entry() gtklogger.setWidgetName(self.xtext, "X") self.xtext.set_size_request(10 * guitop.top().digitsize, -1) self.table.attach(self.xtext, 1, 2, 0, 1, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) label = gtk.Label('y=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 1, 2, xpadding=5, xoptions=gtk.FILL) self.ytext = gtk.Entry() gtklogger.setWidgetName(self.ytext, "Y") self.ytext.set_size_request(10 * guitop.top().digitsize, -1) self.table.attach(self.ytext, 1, 2, 1, 2, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) self.xtsignal = gtklogger.connect(self.xtext, 'changed', self.pointChanged) self.ytsignal = gtklogger.connect(self.ytext, 'changed', self.pointChanged) box = gtk.HBox(homogeneous=True, spacing=2) self.updatebutton = gtkutils.StockButton(gtk.STOCK_REFRESH, 'Update') box.pack_start(self.updatebutton, expand=1, fill=1) gtklogger.setWidgetName(self.updatebutton, "Update") gtklogger.connect(self.updatebutton, 'clicked', self.updateButtonCB) self.clearbutton = gtkutils.StockButton(gtk.STOCK_CLEAR, 'Clear') box.pack_start(self.clearbutton, expand=1, fill=1) gtklogger.setWidgetName(self.clearbutton, "Clear") gtklogger.connect(self.clearbutton, 'clicked', self.clearButtonCB) self.table.attach(box, 0, 2, 2, 3, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.updatebutton.set_sensitive(0) self.clearbutton.set_sensitive(0) self.buildGUI() self.sbcallbacks = [ switchboard.requestCallbackMain(pixelinfotoolbox, self.update), switchboard.requestCallbackMain('new pixelinfo plugin', self.buildGUI), switchboard.requestCallbackMain( (self.gfxwindow(), 'layers changed'), self.update) ]
def shutdown(exitstatus): gui = guitop.top() if gui: gui.stop() gui.destroy() ooflib.common.quit.shutdown(exitstatus)
def __init__(self, title, menu=None, callback=None, guiloggable=True): debug.mainthreadTest() self.gtk = gtk.Window(gtk.WINDOW_TOPLEVEL) self.gtk.set_title(title) if guiloggable: gtklogger.newTopLevelWidget(self.gtk, title) gtklogger.connect_passive(self.gtk, 'delete-event') gtklogger.connect_passive(self.gtk, 'configure-event') self.mainbox = gtk.VBox() self.gtk.add(self.mainbox) # Checking the type is clumsy; the idea is that the caller # must provide either the name for the auto-generated menu, or # a menu to use instead. TODO LATER: It would be cleaner for # the Layer Editor and the Activity Viewer if the SubWindow # class could provide the window-specific (i.e "Close" and # "Quit") menu items under "File" (creating it, if necessary, # and prepending it to the passed-in menu) even when a menu is # passed in. This would prevent duplication of effort by # separate subclasses of subwindow. if type(menu)==types.StringType: # If no menu is provided, then build a non-logging local # one with 'Close' and 'Quit'. self.subwindow_menu = oofmenu.OOFMenuItem( menu, secret=1, gui_only=1, no_log=1) file_item = oofmenu.OOFMenuItem('File', gui_only=1, no_log=1) self.subwindow_menu.addItem(file_item) file_item.addItem(oofmenu.OOFMenuItem( 'Close', help="Close this window.", callback=self.menu_close, no_log=1, gui_only=1, accel='w')) file_item.addItem(oofmenu.OOFMenuItem( 'Quit', gui_callback=quit.queryQuit, no_log=1, gui_only=1, help="Quit the OOF application.", accel='q', threadable = oofmenu.UNTHREADABLE)) mainmenu.OOF.addItem(self.subwindow_menu) self._local_menu = menu elif isinstance(menu, oofmenu.OOFMenuItem): self.subwindow_menu = menu self._local_menu = None # Flag indicating menu was passed in. else: raise TypeError("Incorrect type passed as menu to SubWindow.") # Build the menu bar and add it to the window. ## self.menu_bar = None self.accel_group = gtk.AccelGroup() self.gtk.add_accel_group(self.accel_group) self.menu_bar = gfxmenu.gtkOOFMenuBar( self.subwindow_menu, accelgroup=self.accel_group) if guiloggable: gtklogger.setWidgetName(self.menu_bar, "MenuBar") self.mainbox.pack_start(self.menu_bar, fill=0, expand=0) # Add the "Windows" menu to the bar. self.windows_gtk_menu_item = gfxmenu.gtkOOFMenu(mainmenu.OOF.Windows, self.accel_group) self.menu_bar.append(self.windows_gtk_menu_item) self.menu_bar.connect("destroy", self.menu_bar_destroyed) if callback is None: callback = self.destroySubWindow top().gtk.connect("destroy", callback)
def __init__(self, toolbox, table, row): debug.mainthreadTest() pixelinfoplugin.PixelInfoPlugIn.__init__(self, toolbox) # colorv is set by "update" and "nonsense", it can be None (no # color), "Nonsense", or a color.Color object. # Statefulness is needed to remain consistency when a user # switches from RGB to HSV or vice versa. self.colorv = None label = gtk.Label('image=') label.set_alignment(1.0, 0.5) table.attach(label, 0, 1, row, row + 1, xpadding=5, xoptions=gtk.FILL) self.imagetext = gtk.Entry() gtklogger.setWidgetName(self.imagetext, "Image") self.imagetext.set_size_request(12 * guitop.top().charsize, -1) self.imagetext.set_editable(0) table.attach(self.imagetext, 1, 2, row, row + 1, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) selectorbox = gtk.HBox() self.rgb_selector = gtk.RadioButton(group=None, label="RGB") tooltips.set_tooltip_text( self.rgb_selector, "View color values in Red-Green-Blue format.") selectorbox.add(self.rgb_selector) self.hsv_selector = gtk.RadioButton(group=self.rgb_selector, label="HSV") tooltips.set_tooltip_text( self.hsv_selector, "View color values in Hue-Saturation-Value format.") selectorbox.add(self.hsv_selector) self.rgb_selector.set_active(1) # Default. # Because this is a two-element group of radio buttons, only # need to connect to the toggle signal on one of the buttons. # If more buttons get added, this strategy will fail. gtklogger.setWidgetName(self.rgb_selector, "RGB selector") # "toggle" signal is not actually logged. # gtklogger.connect(self.rgb_selector, "toggled", self.selector_cb) gtklogger.setWidgetName(self.hsv_selector, "HSV selector") gtklogger.connect(self.rgb_selector, "clicked", self.selector_cb) gtklogger.connect(self.hsv_selector, "clicked", self.selector_cb) table.attach(selectorbox, 0, 2, row + 1, row + 2, xoptions=gtk.EXPAND | gtk.FILL) self.label1 = gtk.Label('red=') self.label1.set_alignment(1.0, 0.5) table.attach(self.label1, 0, 1, row + 2, row + 3, xpadding=5, xoptions=gtk.FILL) self.text1 = gtk.Entry() gtklogger.setWidgetName(self.text1, 'Text 1') self.text1.set_size_request(10 * guitop.top().digitsize, -1) self.text1.set_editable(0) table.attach(self.text1, 1, 2, row + 2, row + 3, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) self.label2 = gtk.Label('green=') self.label2.set_alignment(1.0, 0.5) table.attach(self.label2, 0, 1, row + 3, row + 4, xpadding=5, xoptions=gtk.FILL) self.text2 = gtk.Entry() gtklogger.setWidgetName(self.text2, 'Text 2') self.text2.set_size_request(10 * guitop.top().digitsize, -1) self.text2.set_editable(0) table.attach(self.text2, 1, 2, row + 3, row + 4, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) self.label3 = gtk.Label('blue=') self.label3.set_alignment(1.0, 0.5) table.attach(self.label3, 0, 1, row + 4, row + 5, xpadding=5, xoptions=gtk.FILL) self.text3 = gtk.Entry() gtklogger.setWidgetName(self.text3, 'Text 3') self.text3.set_size_request(10 * guitop.top().digitsize, -1) self.text3.set_editable(0) table.attach(self.text3, 1, 2, row + 4, row + 5, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) self.sbcallbacks = [ switchboard.requestCallbackMain('modified image', self.image_changed) ]
def __init__thread(self, gfxwindow, time, position, output): debug.mainthreadTest() allMeshDataWindows.append(self) widgetscope.WidgetScope.__init__(self, None) current_count = MeshDataGUI.count MeshDataGUI.count += 1 self._name = "Mesh_Data_%d" % current_count self.output = output self.time = time self.position = position self.sbcallbacks = [] self.gsbcallbacks = [] # callbacks from a specific gfx window self.updateLock = lock.Lock() self.outputparam = \ ooflib.engine.IO.output.AggregateOutputParameter('output') # Although it's not displayed, we need a mesh widget in the # widgetscope, or the OutputParameterWidget won't work. # TODO LATER: Is this ugly, or what? self.meshWidget = whowidget.WhoWidget(mesh.meshes, scope=self, name="Godot") self.gtk = gtk.Window(gtk.WINDOW_TOPLEVEL) title = utils.underscore2space(self._name) self.gtk.set_title(title) gtklogger.newTopLevelWidget(self.gtk, title) gtklogger.connect_passive(self.gtk, 'delete-event') gtklogger.connect_passive(self.gtk, 'configure-event') self.mainbox = gtk.VBox() self.gtk.add(self.mainbox) # Put this window into the Windows menu. The menu item can't # be logged, since the creation and operation of the window # aren't logged, so scripts shouldn't refer to it at all. mainmenu.OOF.Windows.Mesh_Data.addItem(oofmenu.OOFMenuItem( self._name, no_log=1, help="Raise Mesh Data window %d." % current_count, threadable=oofmenu.UNTHREADABLE, callback=self.raiseWindow)) expander = gtk.Expander("Source") gtklogger.setWidgetName(expander, 'ViewSource') gtklogger.connect_passive_after(expander, 'activate') self.mainbox.pack_start(expander) expander.set_expanded(1) self.table = gtk.Table(rows=config.dimension()+4, columns=2) expander.add(self.table) label = gtk.Label("Source Window:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 0,1, xpadding=3, xoptions=gtk.FILL) tooltips.set_tooltip_text(label, "Display data for mouse clicks in this Graphics window.") self.gfxWindowChooser = chooser.ChooserWidget([], callback=self.chooserCB, name='GfxWindow') self.table.attach(self.gfxWindowChooser.gtk, 1,2, 0,1, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) label = gtk.Label("Mesh:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 1,2, xpadding=3, xoptions=gtk.FILL, yoptions=0) tooltips.set_tooltip_text(label,"Data is displayed for values on this mesh.") self.meshText = gtk.Entry() gtklogger.setWidgetName(self.meshText, "meshname") self.meshText.set_editable(False) self.meshText.set_size_request(12*guitop.top().charsize, -1) self.table.attach(self.meshText, 1,2, 1,2, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) # Position controls label = gtk.Label("position x:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 2,3, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.xText = gtk.Entry() gtklogger.setWidgetName(self.xText, 'x') self.xText.set_size_request(12*guitop.top().digitsize, -1) self.table.attach(self.xText, 1,2, 2,3, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) self.xsignal = gtklogger.connect(self.xText, 'changed', self.posChangedCB) label = gtk.Label("position y:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 3,4, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.yText = gtk.Entry() gtklogger.setWidgetName(self.yText, 'y') self.yText.set_size_request(12*guitop.top().digitsize, -1) self.table.attach(self.yText, 1,2, 3,4, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) self.ysignal = gtklogger.connect(self.yText, 'changed', self.posChangedCB) if config.dimension() == 3: label = gtk.Label("position z:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 4,5, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.zText = gtk.Entry() gtklogger.setWidgetName(self.zText, 'z') self.zText.set_size_request(12*guitop.top().digitsize, -1) self.table.attach(self.zText, 1,2, 4,5, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) self.zsignal = gtklogger.connect(self.zText, 'changed', self.posChangedCB) timerow = 5 else: timerow = 6 # Time controls. Typing in the time widget does not # immediately update the displayed data, because interpolating # to a new time is an expensive computation, and shouldn't be # done while the user is in the middle of typing. Instead, # the time widget is normally desensitized and uneditable. # When the user clicks the "Edit" button, the widget becomes # editable, the rest of the window is desensitized, and the # "Edit" button changes do a "Done" button. When the user # clicks "Done" the data is updated and the time widget # becomes uneditable again. label = gtk.Label("time:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, timerow,timerow+1, xpadding=3, xoptions=gtk.FILL, yoptions=0) tBox = gtk.HBox(spacing=3) self.table.attach(tBox, 1,2, timerow,timerow+1, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) self.tText = gtk.Entry() self.tText.set_editable(False) self.tText.set_sensitive(False) tBox.pack_start(self.tText, expand=1, fill=1) gtklogger.setWidgetName(self.tText, 't') self.tText.set_size_request(12*guitop.top().digitsize, -1) self.tEditButton = gtk.Button("Edit") tBox.pack_start(self.tEditButton, expand=0, fill=0) gtklogger.setWidgetName(self.tEditButton, "tEdit") gtklogger.connect(self.tEditButton, 'clicked', self.tEditCB) self.tEditMode = False # Output selection label = gtk.Label("Output:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, timerow+2,timerow+3, xpadding=3, xoptions=gtk.FILL, yoptions=0) tooltips.set_tooltip_text(label,"Choose which data is displayed.") self.outputwidget = self.outputparam.makeWidget(scope=self) self.table.attach(self.outputwidget.gtk, 1,2, timerow+2,timerow+3, xpadding=3, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0) switchboard.requestCallback(self.outputwidget, self.outputwidgetCB) # Data display panel hbox = gtk.HBox() self.mainbox.pack_start(hbox, expand=1, fill=1, padding=5) frame = gtk.Frame("Data") gtklogger.setWidgetName(frame, 'Data') frame.set_shadow_type(gtk.SHADOW_IN) hbox.pack_start(frame, expand=1, fill=1, padding=5) vbox = gtk.VBox() frame.add(vbox) self.databox = gtk.HBox() vbox.pack_start(self.databox, expand=1, fill=1, padding=3) self.datawidget = None # set by updateData # Buttons at the bottom of the window buttonbox = gtk.HBox() self.mainbox.pack_start(buttonbox, expand=0, fill=0, padding=3) # Freeze buttons freezeframe = gtk.Frame("Freeze") gtklogger.setWidgetName(freezeframe, "Freeze") buttonbox.pack_start(freezeframe, expand=1, fill=1, padding=3) hbox = gtk.HBox() freezeframe.add(hbox) # Freeze Space button self.freezeSpaceFlag = False self.freezeSpaceButton = gtk.CheckButton('Space') gtklogger.setWidgetName(self.freezeSpaceButton, 'Space') hbox.pack_start(self.freezeSpaceButton, expand=1, fill=0, padding=0) self.freezeSpaceButton.set_active(self.freezeSpaceFlag) gtklogger.connect(self.freezeSpaceButton, 'clicked', self.freezeSpaceButtonCB) tooltips.set_tooltip_text(self.freezeSpaceButton, "Prevent the data in this window from being updated when the sample position changes.") # Freeze Time button self.freezeTimeFlag = False self.freezeTimeButton = gtk.CheckButton('Time') gtklogger.setWidgetName(self.freezeTimeButton, "Time") hbox.pack_start(self.freezeTimeButton, expand=1, fill=0, padding=0) self.freezeTimeButton.set_active(self.freezeTimeFlag) gtklogger.connect(self.freezeTimeButton,'clicked', self.freezeTimeButtonCB) tooltips.set_tooltip_text(self.freezeTimeButton, "Prevent the data in this window from being updated when the Mesh's time changes.") # Clone button self.cloneButton = gtkutils.StockButton(gtk.STOCK_COPY, 'Clone') gtklogger.setWidgetName(self.cloneButton, 'Clone') gtklogger.connect(self.cloneButton, 'clicked', self.cloneButtonCB) buttonbox.pack_start(self.cloneButton, expand=0, fill=0, padding=3) tooltips.set_tooltip_text(self.cloneButton, "Make a copy of this window with its current settings.") # Close button self.closeButton = gtk.Button(stock=gtk.STOCK_CLOSE) gtklogger.setWidgetName(self.closeButton, 'Close') gtklogger.connect(self.closeButton, 'clicked', self.closeButtonCB) buttonbox.pack_end(self.closeButton, expand=0, fill=0, padding=3) self.gtk.connect('destroy', self.destroyCB) self.updateGfxWindowChooser() if gfxwindow: self.gfxWindowChooser.set_state(gfxwindow.name) if position is not None: self.updatePosition(position) self.currentMesh = None self.updateMesh() self.setupSwitchboard() # gfx window dependent callbacks self.sbcallbacks += [ switchboard.requestCallbackMain('open graphics window', self.gfxwindowChanged), switchboard.requestCallbackMain('close graphics window', self.gfxwindowChanged), switchboard.requestCallbackMain('mesh data changed', self.meshDataChanged), switchboard.requestCallbackMain((gfxwindow, "time changed"), self.timeChanged) ] self.gtk.show_all()
def __init__(self, movenodetoolbox): debug.mainthreadTest() self.downed = 0 # is the mouse button down? self.moving = 0 # in the middle of a move self.movingnode = None # node being moved # writable should only be set by self.set_writable, which # issues a checkpoint. self.writable = True # is the top most Skeleton writable? self.mode = "Mouse" self.mouselock = lock.Lock() toolboxGUI.GfxToolbox.__init__(self, "Move Nodes", movenodetoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) hbox = gtk.HBox() mainbox.pack_start(hbox, expand=0, fill=0) gtklogger.setWidgetName(hbox, "MoveWith") hbox.pack_start(gtk.Label("Move with: "), expand=0, fill=0) modes = [("Mouse", "Click and drag a node to move it."), ("Keyboard", "Select a node, type a position, and click the Move button") ] self.modebuttons = [] for mode, tip in modes: if self.modebuttons: button = gtk.RadioButton(label=mode, group=self.modebuttons[0]) else: button = gtk.RadioButton(label=mode) gtklogger.setWidgetName(button, mode) self.modebuttons.append(button) tooltips.set_tooltip_text(button,tip) hbox.pack_start(button, expand=0, fill=0) button.set_active(self.mode is mode) gtklogger.connect(button, 'clicked', self.changeMode, mode) # allow illegal move? self.allow_illegal = gtk.CheckButton("Allow illegal moves") gtklogger.setWidgetName(self.allow_illegal, "AllowIllegal") mainbox.pack_start(self.allow_illegal, expand=0, fill=0, padding=1) mainbox.pack_start(gtk.HSeparator(), expand=0, fill=0, padding=3) gtklogger.connect(self.allow_illegal, "clicked", self.illegal_status) if movenodetoolbox.allow_illegal: self.allow_illegal.set_active(1) else: self.allow_illegal.set_active(0) if config.dimension() == 2: self.table = gtk.Table(columns=2, rows=6) r = 2 elif config.dimension() == 3: self.table = gtk.Table(columns=2, rows=8) r = 3 mainbox.pack_start(self.table, expand=0, fill=0) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 0,1, xpadding=5, xoptions=gtk.FILL) self.xtext = gtk.Entry() gtklogger.setWidgetName(self.xtext, "x") self.xsignal = gtklogger.connect_passive(self.xtext, 'changed') self.xtext.set_size_request(12*guitop.top().digitsize, -1) self.xtext.set_editable(1) self.table.attach(self.xtext, 1,2, 0,1, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.xtext,"x position of the mouse") label = gtk.Label('y=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 1,2, xpadding=5, xoptions=gtk.FILL) self.ytext = gtk.Entry() gtklogger.setWidgetName(self.ytext, 'y') self.ysignal = gtklogger.connect_passive(self.ytext, 'changed') self.ytext.set_size_request(12*guitop.top().digitsize, -1) self.ytext.set_editable(1) self.table.attach(self.ytext, 1,2, 1,2, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.ytext,"y position of the mouse") if config.dimension() == 3: label = gtk.Label('z=') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 2,3, xpadding=5, xoptions=gtk.FILL) self.ztext = gtk.Entry() gtklogger.setWidgetName(self.ztext, 'z') self.zsignal = gtklogger.connect_passive(self.ztext, 'changed') self.ztext.set_size_request(12*guitop.top().digitsize, -1) self.ztext.set_editable(1) self.table.attach(self.ztext, 1,2, 2,3, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.ztext,"z position of the mouse") label = gtk.Label("Change in... ") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, r,r+1, xpadding=4, xoptions=gtk.EXPAND|gtk.FILL) label = gtk.Label("shape energy=") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, r+1,r+2, xpadding=5, xoptions=gtk.FILL) self.shapetext = gtk.Entry() self.shapetext.set_editable(0) gtklogger.setWidgetName(self.shapetext,"shape") self.shapetext.set_size_request(12*guitop.top().digitsize, -1) self.table.attach(self.shapetext, 1,2, r+1,r+2, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.shapetext,"total change in shape energy") label = gtk.Label("homogeneity=") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, r+2,r+3, xpadding=5, xoptions=gtk.FILL) self.homogtext = gtk.Entry() self.homogtext.set_editable(0) gtklogger.setWidgetName(self.homogtext,"homog") self.homogtext.set_size_request(12*guitop.top().digitsize, -1) self.table.attach(self.homogtext, 1,2, r+2,r+3, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.homogtext,"total change in homogeneity") mainbox.pack_start(gtk.HSeparator(), expand=0, fill=0, padding=3) self.statusText = gtk.Label() gtklogger.setWidgetName(self.statusText, "Status") mainbox.pack_start(self.statusText, expand=0, fill=0, padding=3) bbox = gtk.HBox(homogeneous=1, spacing=2) mainbox.pack_end(bbox, expand=0, fill=0, padding=3) self.undobutton = gtk.Button(stock=gtk.STOCK_UNDO) tooltips.set_tooltip_text(self.undobutton,"Undo the latest node move.") self.movebutton = gtk.Button('Move') tooltips.set_tooltip_text(self.movebutton, "Move the selected node to the specified position.") self.redobutton = gtk.Button(stock=gtk.STOCK_REDO) tooltips.set_tooltip_text(self.redobutton,"Redo the latest UNDO.") gtklogger.setWidgetName(self.undobutton, 'Undo') gtklogger.setWidgetName(self.redobutton, 'Redo') gtklogger.setWidgetName(self.movebutton, 'Move') bbox.pack_start(self.undobutton, expand=1, fill=1) bbox.pack_start(self.movebutton, expand=1, fill=1) bbox.pack_start(self.redobutton, expand=1, fill=1) gtklogger.connect(self.undobutton, 'clicked', self.undoCB) gtklogger.connect(self.movebutton, 'clicked', self.moveCB) gtklogger.connect(self.redobutton, 'clicked', self.redoCB) self.sbcallbacks = [ switchboard.requestCallbackMain(('who changed', 'Skeleton'), self.skelChanged), switchboard.requestCallbackMain("made reservation", self.rsrvChanged, 1), switchboard.requestCallbackMain("cancelled reservation", self.rsrvChanged, 0), switchboard.requestCallbackMain(("node selected", movenodetoolbox), self.nodeSelected), switchboard.requestCallbackMain(("illegal-move status changed", movenodetoolbox), self.illegal_status_changed), switchboard.requestCallbackMain(("skeleton changed", movenodetoolbox), self.layersChanged) ] self.move_info(None, '---', '---', '')
def __init__thread(self, gfxwindow, time, position, output): debug.mainthreadTest() allMeshDataWindows.append(self) widgetscope.WidgetScope.__init__(self, None) current_count = MeshDataGUI.count MeshDataGUI.count += 1 self._name = "Mesh_Data_%d" % current_count self.output = output self.time = time self.position = position self.sbcallbacks = [] self.gsbcallbacks = [] # callbacks from a specific gfx window self.updateLock = lock.Lock() self.outputparam = \ ooflib.engine.IO.output.AggregateOutputParameter('output') # Although it's not displayed, we need a mesh widget in the # widgetscope, or the OutputParameterWidget won't work. # TODO LATER: Is this ugly, or what? self.meshWidget = whowidget.WhoWidget(mesh.meshes, scope=self, name="Godot") self.gtk = gtk.Window(gtk.WINDOW_TOPLEVEL) title = utils.underscore2space(self._name) self.gtk.set_title(title) gtklogger.newTopLevelWidget(self.gtk, title) gtklogger.connect_passive(self.gtk, 'delete-event') gtklogger.connect_passive(self.gtk, 'configure-event') self.mainbox = gtk.VBox() self.gtk.add(self.mainbox) # Put this window into the Windows menu. The menu item can't # be logged, since the creation and operation of the window # aren't logged, so scripts shouldn't refer to it at all. mainmenu.OOF.Windows.Mesh_Data.addItem( oofmenu.OOFMenuItem(self._name, no_log=1, help="Raise Mesh Data window %d." % current_count, threadable=oofmenu.UNTHREADABLE, callback=self.raiseWindow)) expander = gtk.Expander("Source") gtklogger.setWidgetName(expander, 'ViewSource') gtklogger.connect_passive_after(expander, 'activate') self.mainbox.pack_start(expander) expander.set_expanded(1) self.table = gtk.Table(rows=config.dimension() + 4, columns=2) expander.add(self.table) label = gtk.Label("Source Window:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 0, 1, xpadding=3, xoptions=gtk.FILL) tooltips.set_tooltip_text( label, "Display data for mouse clicks in this Graphics window.") self.gfxWindowChooser = chooser.ChooserWidget([], callback=self.chooserCB, name='GfxWindow') self.table.attach(self.gfxWindowChooser.gtk, 1, 2, 0, 1, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) label = gtk.Label("Mesh:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 1, 2, xpadding=3, xoptions=gtk.FILL, yoptions=0) tooltips.set_tooltip_text( label, "Data is displayed for values on this mesh.") self.meshText = gtk.Entry() gtklogger.setWidgetName(self.meshText, "meshname") self.meshText.set_editable(False) self.meshText.set_size_request(12 * guitop.top().charsize, -1) self.table.attach(self.meshText, 1, 2, 1, 2, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) # Position controls label = gtk.Label("position x:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 2, 3, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.xText = gtk.Entry() gtklogger.setWidgetName(self.xText, 'x') self.xText.set_size_request(12 * guitop.top().digitsize, -1) self.table.attach(self.xText, 1, 2, 2, 3, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.xsignal = gtklogger.connect(self.xText, 'changed', self.posChangedCB) label = gtk.Label("position y:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 3, 4, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.yText = gtk.Entry() gtklogger.setWidgetName(self.yText, 'y') self.yText.set_size_request(12 * guitop.top().digitsize, -1) self.table.attach(self.yText, 1, 2, 3, 4, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.ysignal = gtklogger.connect(self.yText, 'changed', self.posChangedCB) if config.dimension() == 3: label = gtk.Label("position z:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, 4, 5, xpadding=3, xoptions=gtk.FILL, yoptions=0) self.zText = gtk.Entry() gtklogger.setWidgetName(self.zText, 'z') self.zText.set_size_request(12 * guitop.top().digitsize, -1) self.table.attach(self.zText, 1, 2, 4, 5, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.zsignal = gtklogger.connect(self.zText, 'changed', self.posChangedCB) timerow = 5 else: timerow = 6 # Time controls. Typing in the time widget does not # immediately update the displayed data, because interpolating # to a new time is an expensive computation, and shouldn't be # done while the user is in the middle of typing. Instead, # the time widget is normally desensitized and uneditable. # When the user clicks the "Edit" button, the widget becomes # editable, the rest of the window is desensitized, and the # "Edit" button changes do a "Done" button. When the user # clicks "Done" the data is updated and the time widget # becomes uneditable again. label = gtk.Label("time:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, timerow, timerow + 1, xpadding=3, xoptions=gtk.FILL, yoptions=0) tBox = gtk.HBox(spacing=3) self.table.attach(tBox, 1, 2, timerow, timerow + 1, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.tText = gtk.Entry() self.tText.set_editable(False) self.tText.set_sensitive(False) tBox.pack_start(self.tText, expand=1, fill=1) gtklogger.setWidgetName(self.tText, 't') self.tText.set_size_request(12 * guitop.top().digitsize, -1) self.tEditButton = gtk.Button("Edit") tBox.pack_start(self.tEditButton, expand=0, fill=0) gtklogger.setWidgetName(self.tEditButton, "tEdit") gtklogger.connect(self.tEditButton, 'clicked', self.tEditCB) self.tEditMode = False # Output selection label = gtk.Label("Output:") label.set_alignment(1.0, 0.5) self.table.attach(label, 0, 1, timerow + 2, timerow + 3, xpadding=3, xoptions=gtk.FILL, yoptions=0) tooltips.set_tooltip_text(label, "Choose which data is displayed.") self.outputwidget = self.outputparam.makeWidget(scope=self) self.table.attach(self.outputwidget.gtk, 1, 2, timerow + 2, timerow + 3, xpadding=3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) switchboard.requestCallback(self.outputwidget, self.outputwidgetCB) # Data display panel hbox = gtk.HBox() self.mainbox.pack_start(hbox, expand=1, fill=1, padding=5) frame = gtk.Frame("Data") gtklogger.setWidgetName(frame, 'Data') frame.set_shadow_type(gtk.SHADOW_IN) hbox.pack_start(frame, expand=1, fill=1, padding=5) vbox = gtk.VBox() frame.add(vbox) self.databox = gtk.HBox() vbox.pack_start(self.databox, expand=1, fill=1, padding=3) self.datawidget = None # set by updateData # Buttons at the bottom of the window buttonbox = gtk.HBox() self.mainbox.pack_start(buttonbox, expand=0, fill=0, padding=3) # Freeze buttons freezeframe = gtk.Frame("Freeze") gtklogger.setWidgetName(freezeframe, "Freeze") buttonbox.pack_start(freezeframe, expand=1, fill=1, padding=3) hbox = gtk.HBox() freezeframe.add(hbox) # Freeze Space button self.freezeSpaceFlag = False self.freezeSpaceButton = gtk.CheckButton('Space') gtklogger.setWidgetName(self.freezeSpaceButton, 'Space') hbox.pack_start(self.freezeSpaceButton, expand=1, fill=0, padding=0) self.freezeSpaceButton.set_active(self.freezeSpaceFlag) gtklogger.connect(self.freezeSpaceButton, 'clicked', self.freezeSpaceButtonCB) tooltips.set_tooltip_text( self.freezeSpaceButton, "Prevent the data in this window from being updated when the sample position changes." ) # Freeze Time button self.freezeTimeFlag = False self.freezeTimeButton = gtk.CheckButton('Time') gtklogger.setWidgetName(self.freezeTimeButton, "Time") hbox.pack_start(self.freezeTimeButton, expand=1, fill=0, padding=0) self.freezeTimeButton.set_active(self.freezeTimeFlag) gtklogger.connect(self.freezeTimeButton, 'clicked', self.freezeTimeButtonCB) tooltips.set_tooltip_text( self.freezeTimeButton, "Prevent the data in this window from being updated when the Mesh's time changes." ) # Clone button self.cloneButton = gtkutils.StockButton(gtk.STOCK_COPY, 'Clone') gtklogger.setWidgetName(self.cloneButton, 'Clone') gtklogger.connect(self.cloneButton, 'clicked', self.cloneButtonCB) buttonbox.pack_start(self.cloneButton, expand=0, fill=0, padding=3) tooltips.set_tooltip_text( self.cloneButton, "Make a copy of this window with its current settings.") # Close button self.closeButton = gtk.Button(stock=gtk.STOCK_CLOSE) gtklogger.setWidgetName(self.closeButton, 'Close') gtklogger.connect(self.closeButton, 'clicked', self.closeButtonCB) buttonbox.pack_end(self.closeButton, expand=0, fill=0, padding=3) self.gtk.connect('destroy', self.destroyCB) self.updateGfxWindowChooser() if gfxwindow: self.gfxWindowChooser.set_state(gfxwindow.name) if position is not None: self.updatePosition(position) self.currentMesh = None self.updateMesh() self.setupSwitchboard() # gfx window dependent callbacks self.sbcallbacks += [ switchboard.requestCallbackMain('open graphics window', self.gfxwindowChanged), switchboard.requestCallbackMain('close graphics window', self.gfxwindowChanged), switchboard.requestCallbackMain('mesh data changed', self.meshDataChanged), switchboard.requestCallbackMain((gfxwindow, "time changed"), self.timeChanged) ] self.gtk.show_all()
def __init__(self, pinnodestoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Pin Nodes", pinnodestoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) infoframe = gtk.Frame() mainbox.pack_start(infoframe, expand=0, fill=0) info = gtk.Label("""Click a node to pin it, Shift-click to unpin it, And Ctrl-click to toggle.""") infoframe.add(info) if config.dimension() == 2: self.table = gtk.Table(columns=3, rows=5) r = 2 # variable used to make 2D and 3D code overlap better elif config.dimension() == 3: self.table = gtk.Table(columns=3, rows=7) r = 3 mainbox.pack_start(self.table, expand=0, fill=0) label = gtk.Label('Mouse') label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, 0,r, xpadding=2, xoptions=0) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, 0,1, xpadding=2, xoptions=gtk.FILL) self.xtext = gtk.Entry() gtklogger.setWidgetName(self.xtext,"Mouse X") self.xtext.set_size_request(12*guitop.top().digitsize, -1) self.xtext.set_editable(0) self.table.attach(self.xtext, 2,3, 0,1, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.xtext,"x position of the mouse") label = gtk.Label('y=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, 1,2, xpadding=2, xoptions=gtk.FILL) self.ytext = gtk.Entry() gtklogger.setWidgetName(self.ytext,"Mouse Y") self.ytext.set_size_request(12*guitop.top().digitsize, -1) self.ytext.set_editable(0) self.table.attach(self.ytext, 2,3, 1,2, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.ytext,"y position of the mouse") if config.dimension() == 3: label = gtk.Label('z=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, 2,3, xpadding=2, xoptions=gtk.FILL) self.ztext = gtk.Entry() gtklogger.setWidgetName(self.ztext,"Mouse Z") self.ztext.set_size_request(12*guitop.top().digitsize, -1) self.ztext.set_editable(0) self.table.attach(self.ztext, 2,3, 2,3, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) tooltips.set_tooltip_text(self.ztext,"z position of the mouse") self.table.set_row_spacing(r-1, 5) label = gtk.Label("Node") label.set_alignment(1.0, 0.5) self.table.attach(label, 0,1, r,r+2, xpadding=2, xoptions=0) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, r,r+1, xpadding=2, xoptions=gtk.FILL) self.nodextext = gtk.Entry() gtklogger.setWidgetName(self.nodextext,"Node X") self.nodextext.set_size_request(12*guitop.top().digitsize, -1) self.nodextext.set_editable(0) self.table.attach(self.nodextext, 2,3, r,r+1, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) r += 1 label = gtk.Label('y=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, r,r+1, xpadding=2, xoptions=gtk.FILL) self.nodeytext = gtk.Entry() gtklogger.setWidgetName(self.nodeytext,"Node Y") self.nodeytext.set_size_request(12*guitop.top().digitsize, -1) self.nodeytext.set_editable(0) self.table.attach(self.nodeytext, 2,3, r,r+1, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) r += 1 if config.dimension() == 3: label = gtk.Label('z=') label.set_alignment(1.0, 0.5) self.table.attach(label, 1,2, r,r+1, xpadding=2, xoptions=gtk.FILL) self.nodeztext = gtk.Entry() gtklogger.setWidgetName(self.nodeztext,"Node Z") self.nodeztext.set_size_request(12*guitop.top().digitsize, -1) self.nodeztext.set_editable(0) self.table.attach(self.nodeztext, 2,3, r,r+1, xpadding=2, xoptions=gtk.EXPAND|gtk.FILL) r += 1 self.pintext = gtk.Label() gtklogger.setWidgetName(self.pintext,"Pin Label") self.pintext.set_alignment(0.0, 0.5) self.table.attach(self.pintext, 2,3, r,r+1, xpadding=5, xoptions=gtk.EXPAND|gtk.FILL) modbox = gtk.VBox() mainbox.pack_end(modbox, expand=0, fill=0) bbox1 = gtk.HBox(homogeneous=True, spacing=2) modbox.pack_end(bbox1, expand=0, fill=0, padding=2) self.undobutton = gtk.Button(stock=gtk.STOCK_UNDO) gtklogger.setWidgetName(self.undobutton, 'Undo') gtklogger.connect(self.undobutton, "clicked", self.undoCB) tooltips.set_tooltip_text(self.undobutton,"Undo the latest action.") bbox1.pack_start(self.undobutton, expand=1, fill=1) self.redobutton = gtk.Button(stock=gtk.STOCK_REDO) gtklogger.setWidgetName(self.redobutton, 'Redo') gtklogger.connect(self.redobutton, "clicked", self.redoCB) tooltips.set_tooltip_text(self.redobutton,"Redo the latest undone action.") bbox1.pack_start(self.redobutton, expand=1, fill=1) bbox2 = gtk.HBox(homogeneous=True, spacing=2) modbox.pack_end(bbox2, expand=0, fill=0, padding=2) self.unpinallbutton = gtk.Button("Unpin All") gtklogger.setWidgetName(self.unpinallbutton, 'UnPinAll') gtklogger.connect(self.unpinallbutton, "clicked", self.unpinallCB) tooltips.set_tooltip_text(self.unpinallbutton,"Unpin all the pinned nodes.") bbox2.pack_start(self.unpinallbutton, expand=1, fill=1) self.invertbutton = gtk.Button("Invert") gtklogger.setWidgetName(self.invertbutton, 'Invert') gtklogger.connect(self.invertbutton, "clicked", self.invertCB) tooltips.set_tooltip_text(self.invertbutton,"Invert - pin the unpinned and unpin the pinned.") bbox2.pack_start(self.invertbutton, expand=1, fill=1) self.status = gtk.Label() gtklogger.setWidgetName(self.status,"Status") self.status.set_alignment(0.0, 0.5) mainbox.pack_end(self.status, expand=0, fill=0, padding=5) # self.skeleton_context is set by self.update(). self.skeleton_context = None self.current_node = None
def _newWindow(self, name, **kwargs): if top(): # if in GUI mode return GfxWindow3D(name, self, **kwargs) return ghostgfxwindow.GhostGfxWindow(name, self, **kwargs)
def __init__(self, viewertoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Viewer", viewertoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) infoframe = gtk.Frame("Position Information") infoframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(infoframe, fill=0, expand=0) infotable = gtk.Table(columns=3, rows=2) infoframe.add(infotable) pixellabel = gtk.Label("Pixel: ") pixellabel.set_alignment(1.0, 0.5) self.pixel_x = gtk.Entry() gtklogger.setWidgetName(self.pixel_x, "PixelX") self.pixel_x.set_size_request(ndigits * guitop.top().digitsize, -1) self.pixel_x.set_editable(0) self.pixel_y = gtk.Entry() gtklogger.setWidgetName(self.pixel_y, "PixelY") self.pixel_y.set_size_request(ndigits * guitop.top().digitsize, -1) self.pixel_y.set_editable(0) physicallabel = gtk.Label("Physical: ") physicallabel.set_alignment(1.0, 0.5) self.physical_x = gtk.Entry() gtklogger.setWidgetName(self.physical_x, "PhysicalX") self.physical_x.set_size_request(ndigits * guitop.top().digitsize, -1) self.physical_x.set_editable(0) self.physical_y = gtk.Entry() gtklogger.setWidgetName(self.physical_y, "PhysicalY") self.physical_y.set_size_request(ndigits * guitop.top().digitsize, -1) self.physical_y.set_editable(0) infotable.attach(pixellabel, 0, 1, 0, 1, xpadding=5, ypadding=2, xoptions=0) infotable.attach(self.pixel_x, 1, 2, 0, 1, xpadding=1, ypadding=2, xoptions=gtk.FILL | gtk.EXPAND) infotable.attach(self.pixel_y, 2, 3, 0, 1, xpadding=1, ypadding=2, xoptions=gtk.FILL | gtk.EXPAND) infotable.attach(physicallabel, 0, 1, 1, 2, xpadding=5, ypadding=2, xoptions=0) infotable.attach(self.physical_x, 1, 2, 1, 2, xpadding=1, ypadding=2, xoptions=gtk.FILL | gtk.EXPAND) infotable.attach(self.physical_y, 2, 3, 1, 2, xpadding=1, ypadding=2, xoptions=gtk.FILL | gtk.EXPAND) zoomframe = gtk.Frame("Zoom") gtklogger.setWidgetName(zoomframe, "Zoom") zoomframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(zoomframe, fill=0, expand=0) zoombox = gtk.VBox() zoomframe.add(zoombox) buttonrow = gtk.HBox(homogeneous=1, spacing=2) zoombox.pack_start(buttonrow, expand=0, fill=1, padding=2) inbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_IN, 'In') buttonrow.pack_start(inbutton, expand=0, fill=1) gtklogger.setWidgetName(inbutton, "In") gtklogger.connect(inbutton, 'clicked', self.inCB) outbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_OUT, 'Out') buttonrow.pack_start(outbutton, expand=0, fill=1) gtklogger.setWidgetName(outbutton, "Out") gtklogger.connect(outbutton, 'clicked', self.outCB) fillbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_FIT, 'Fill') buttonrow.pack_start(fillbutton, expand=0, fill=1) gtklogger.setWidgetName(fillbutton, "Fill") gtklogger.connect(fillbutton, 'clicked', self.fillCB) factorrow = gtk.HBox() zoombox.pack_start(factorrow, expand=0, fill=0, padding=2) factorrow.pack_start(gtk.Label("Zoom Factor: "), expand=0, fill=0) self.zoomfactor = gtk.Entry() self.zoomfactor.set_editable(1) self.zoomfactor.set_size_request(ndigits * guitop.top().digitsize, -1) gtklogger.setWidgetName(self.zoomfactor, "Factor") self.zfactorsignal = gtklogger.connect_passive(self.zoomfactor, "changed") factorrow.pack_start(self.zoomfactor, expand=1, fill=1) zoombox.pack_start(gtk.HSeparator(), fill=0, expand=0, padding=2) label0 = gtk.Label("Shift+Click: Zoom in\nCtrl+Click: Zoom out") label0.set_pattern(" _______\n ________\n") label0.set_justify(gtk.JUSTIFY_LEFT) zoombox.pack_start(label0, fill=0, expand=0, padding=2) align = gtk.Alignment(xalign=0.5) mainbox.pack_end(align, expand=0, fill=0, padding=2) canvas_info = gtkutils.StockButton(gtk.STOCK_DIALOG_INFO, "Canvas Info") gtklogger.setWidgetName(canvas_info, "Info") gtklogger.connect(canvas_info, "clicked", self.canvas_infoCB) tooltips.set_tooltip_text( canvas_info, "Display canvas information in the message window.") align.add(canvas_info) self.currentZFactor = self.gfxwindow().zoomFactor() switchboard.requestCallbackMain("zoom factor changed", self.zfactorCB) # Make sure that the Zoom commands in the graphics windows # Settings menu use an up-to-date zoom factor. self.gfxwindow().menu.Settings.Zoom.In.add_gui_callback( self.wrapMenuZoom) self.gfxwindow().menu.Settings.Zoom.Out.add_gui_callback( self.wrapMenuZoom)
def __init__(self, viewertoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Viewer", viewertoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) # camera position infoframe = gtk.Frame("Camera Info") infoframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(infoframe, fill=0, expand=0) infobox = gtk.VBox() infoframe.add(infobox) positionlabel = gtk.Label("Camera Position:") infobox.pack_start(positionlabel, fill=0, expand=0) positiontable = gtk.Table(columns=3, rows=1) infobox.pack_start(positiontable, fill=0, expand=0) self.camera_x = gtk.Entry() gtklogger.setWidgetName(self.camera_x, "CameraX") self.camera_x.set_size_request(ndigits * guitop.top().digitsize, -1) self.camera_x.set_editable(0) positiontable.attach(self.camera_x, 0, 1, 0, 1) self.camera_y = gtk.Entry() gtklogger.setWidgetName(self.camera_y, "CameraY") self.camera_y.set_size_request(ndigits * guitop.top().digitsize, -1) self.camera_y.set_editable(0) positiontable.attach(self.camera_y, 1, 2, 0, 1) self.camera_z = gtk.Entry() gtklogger.setWidgetName(self.camera_z, "CameraZ") self.camera_z.set_size_request(ndigits * guitop.top().digitsize, -1) self.camera_z.set_editable(0) positiontable.attach(self.camera_z, 2, 3, 0, 1) focalpointlabel = gtk.Label("Focal Point:") infobox.pack_start(focalpointlabel, fill=0, expand=0) focalpointtable = gtk.Table(columns=3, rows=1) infobox.pack_start(focalpointtable, fill=0, expand=0) self.fp_x = gtk.Entry() gtklogger.setWidgetName(self.fp_x, "FocalX") self.fp_x.set_size_request(ndigits * guitop.top().digitsize, -1) self.fp_x.set_editable(0) focalpointtable.attach(self.fp_x, 0, 1, 0, 1) self.fp_y = gtk.Entry() gtklogger.setWidgetName(self.fp_y, "FocalY") self.fp_y.set_size_request(ndigits * guitop.top().digitsize, -1) self.fp_y.set_editable(0) focalpointtable.attach(self.fp_y, 1, 2, 0, 1) self.fp_z = gtk.Entry() gtklogger.setWidgetName(self.fp_z, "FocalZ") self.fp_z.set_size_request(ndigits * guitop.top().digitsize, -1) self.fp_z.set_editable(0) focalpointtable.attach(self.fp_z, 2, 3, 0, 1) viewuplabel = gtk.Label("View Up Vector:") infobox.pack_start(viewuplabel, fill=0, expand=0) viewuptable = gtk.Table(columns=3, rows=1) infobox.pack_start(viewuptable, fill=0, expand=0) self.viewup_x = gtk.Entry() gtklogger.setWidgetName(self.viewup_x, "ViewUpX") self.viewup_x.set_size_request(ndigits * guitop.top().digitsize, -1) self.viewup_x.set_editable(0) viewuptable.attach(self.viewup_x, 0, 1, 0, 1) self.viewup_y = gtk.Entry() gtklogger.setWidgetName(self.viewup_y, "ViewUpY") self.viewup_y.set_size_request(ndigits * guitop.top().digitsize, -1) self.viewup_y.set_editable(0) viewuptable.attach(self.viewup_y, 1, 2, 0, 1) self.viewup_z = gtk.Entry() gtklogger.setWidgetName(self.viewup_z, "ViewUpZ") self.viewup_z.set_size_request(ndigits * guitop.top().digitsize, -1) self.viewup_z.set_editable(0) viewuptable.attach(self.viewup_z, 2, 3, 0, 1) distancetable = gtk.Table(columns=2, rows=1) infobox.pack_start(distancetable, fill=0, expand=0) distancelabel = gtk.Label("Distance:") distancetable.attach(distancelabel, 0, 1, 0, 1) self.distance = gtk.Entry() gtklogger.setWidgetName(self.distance, "Distance") self.distance.set_size_request(ndigits * guitop.top().digitsize, -1) self.distance.set_editable(0) distancetable.attach(self.distance, 1, 2, 0, 1) angletable = gtk.Table(columns=2, rows=1) infobox.pack_start(angletable, fill=0, expand=0) anglelabel = gtk.Label("View Angle:") angletable.attach(anglelabel, 0, 1, 0, 1) self.viewangle = gtk.Entry() gtklogger.setWidgetName(self.viewangle, "ViewAngle") self.viewangle.set_size_request(ndigits * guitop.top().digitsize, -1) self.viewangle.set_editable(0) angletable.attach(self.viewangle, 1, 2, 0, 1) camerainfo = gtkutils.StockButton(gtk.STOCK_DIALOG_INFO, "Camera Info") gtklogger.connect(camerainfo, 'clicked', self.camera_infoCB) tooltips.set_tooltip_text( camerainfo, "Display camera information in the message window.") infobox.pack_start(camerainfo, fill=0, expand=0) # TODO: Do we want to be able to zoom? As in changing the # viewing angle? # Translation # dolly transframe = gtk.Frame("Translation") gtklogger.setWidgetName(transframe, "Translation") transframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(transframe, fill=0, expand=0) transbox = gtk.VBox() transframe.add(transbox) dollyrow = gtk.HBox(homogeneous=1, spacing=2) transbox.pack_start(dollyrow, expand=0, fill=1, padding=2) inbutton = gtk.Button('Dolly In') gtklogger.setWidgetName(inbutton, 'DollyIn') tooltips.set_tooltip_text( inbutton, "Translate camera towards focal point by given factor") dollyrow.pack_start(inbutton, expand=0, fill=1) gtklogger.connect(inbutton, 'clicked', self.dollyin) outbutton = gtk.Button('Dolly Out') gtklogger.setWidgetName(outbutton, 'DollyOut') tooltips.set_tooltip_text( outbutton, "Translate camera away from focal point by given factor") dollyrow.pack_start(outbutton, expand=0, fill=1) gtklogger.connect(outbutton, 'clicked', self.dollyout) fillbutton = gtk.Button('Fill') gtklogger.setWidgetName(fillbutton, 'Fill') tooltips.set_tooltip_text( fillbutton, "Set camera position such that microstructure approximately fills viewport" ) dollyrow.pack_start(fillbutton, expand=0, fill=1) gtklogger.connect(fillbutton, 'clicked', self.dollyfill) factorrow = gtk.HBox() transbox.pack_start(factorrow, expand=0, fill=0, padding=2) factorrow.pack_start(gtk.Label("Factor: "), expand=0, fill=0) self.dollyfactor = gtk.Entry() self.dollyfactor.set_editable(1) self.dollyfactor.set_size_request(ndigits * guitop.top().digitsize, -1) gtklogger.setWidgetName(self.dollyfactor, "DollyFactor") self.dollyfactor.set_text("1.5") tooltips.set_tooltip_text( self.dollyfactor, "Factor by which to multiply distance from camera to focal point") factorrow.pack_start(self.dollyfactor, expand=1, fill=1) # track trackrow = gtk.HBox(homogeneous=1, spacing=2) transbox.pack_start(trackrow, expand=0, fill=1, padding=2) horizbutton = gtk.Button('Horizontal') tooltips.set_tooltip_text(horizbutton, "Shift camera and focal point horizontally") trackrow.pack_start(horizbutton, expand=0, fill=1) gtklogger.connect(horizbutton, 'clicked', self.trackh) vertbutton = gtk.Button('Vertical') tooltips.set_tooltip_text(vertbutton, "Shift camera and focal point vertically") trackrow.pack_start(vertbutton, expand=0, fill=1) gtklogger.connect(vertbutton, 'clicked', self.trackv) recenterbutton = gtk.Button('Recenter') tooltips.set_tooltip_text( recenterbutton, "Recenter the microstructure in the viewport") trackrow.pack_start(recenterbutton, expand=0, fill=1) gtklogger.connect(recenterbutton, 'clicked', self.recenter) distrow = gtk.HBox() transbox.pack_start(distrow, expand=0, fill=0, padding=2) distrow.pack_start(gtk.Label("Distance: "), expand=0, fill=0) self.trackdist = gtk.Entry() self.trackdist.set_editable(1) self.trackdist.set_size_request(ndigits * guitop.top().digitsize, -1) self.trackdist.set_text("10.0") tooltips.set_tooltip_text( self.trackdist, "Distance by which to track camera in units of pixels") distrow.pack_start(self.trackdist, expand=1, fill=1) #rotate rotateframe = gtk.Frame("Rotation") rotateframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(rotateframe, fill=0, expand=0) rotatebox = gtk.VBox() rotateframe.add(rotatebox) rotrow1 = gtk.HBox(homogeneous=1, spacing=2) rotatebox.pack_start(rotrow1, expand=0, fill=1, padding=2) rollbutton = gtk.Button('Roll') tooltips.set_tooltip_text(rollbutton, "Rotate about direction of projection") rotrow1.pack_start(rollbutton, expand=0, fill=1) gtklogger.connect(rollbutton, 'clicked', self.roll) pitchbutton = gtk.Button('Pitch') tooltips.set_tooltip_text( pitchbutton, "Rotate about cross product of direction of projection and view up vector centered at camera position" ) rotrow1.pack_start(pitchbutton, expand=0, fill=1) gtklogger.connect(pitchbutton, 'clicked', self.pitch) yawbutton = gtk.Button('Yaw') tooltips.set_tooltip_text( yawbutton, "Rotate about view up vector centered at camera position") rotrow1.pack_start(yawbutton, expand=0, fill=1) gtklogger.connect(yawbutton, 'clicked', self.yaw) rotrow2 = gtk.HBox(homogeneous=1, spacing=2) rotatebox.pack_start(rotrow2, expand=0, fill=1, padding=2) azbutton = gtk.Button('Azimuth') tooltips.set_tooltip_text( azbutton, "Rotate about view up vector centered at focal point") rotrow2.pack_start(azbutton, expand=0, fill=1) gtklogger.connect(azbutton, 'clicked', self.azimuth) elbutton = gtk.Button('Elevation') tooltips.set_tooltip_text( elbutton, "Rotate about cross product of direction of projection and view up vector centered at focal point" ) rotrow2.pack_start(elbutton, expand=0, fill=1) gtklogger.connect(elbutton, 'clicked', self.elevation) anglerow = gtk.HBox() rotatebox.pack_start(anglerow, expand=0, fill=0, padding=2) anglerow.pack_start(gtk.Label("Angle: "), expand=0, fill=0) self.angle = gtk.Entry() self.angle.set_editable(1) self.angle.set_size_request(ndigits * guitop.top().digitsize, -1) self.angle.set_text("10.0") tooltips.set_tooltip_text(self.angle, "Angle in degrees by which to rotate by") anglerow.pack_start(self.angle, expand=1, fill=1) #clipping planes clippingframe = gtk.Frame("Clipping Range") clippingframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(clippingframe, fill=0, expand=0) clippingbox = gtk.VBox() clippingframe.add(clippingbox) #self.clippingadj = gtk.Adjustment(value=100, lower=0, upper=100, step_incr=-1, page_incr=-5, page_size=0) gtklogger.connect(toolboxGUI.clippingadj, 'value_changed', self.updateview) clippingscale = gtk.HScale(toolboxGUI.clippingadj) clippingscale.set_update_policy(gtk.UPDATE_DELAYED) tooltips.set_tooltip_text( clippingscale, "Adjust the near clipping plane to view cross section") clippingbox.pack_start(clippingscale) # save and restore saverestoreframe = gtk.Frame("Save and Restore Views") saverestoreframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(saverestoreframe, fill=0, expand=0) saverestorebox = gtk.VBox() saverestoreframe.add(saverestorebox) viewtable = gtk.Table(columns=2, rows=2) saverestorebox.pack_start(viewtable, fill=0, expand=0) saveviewbutton = gtk.Button("Save View:") tooltips.set_tooltip_text(saveviewbutton, "Save the current view settings") gtklogger.connect(saveviewbutton, 'clicked', self.saveview) viewtable.attach(saveviewbutton, 0, 1, 0, 1) self.viewname = gtk.Entry() self.viewname.set_editable(1) self.viewname.set_size_request(ndigits * guitop.top().digitsize, -1) tooltips.set_tooltip_text(self.viewname, "Enter a name for the current view") viewtable.attach(self.viewname, 1, 2, 0, 1) setviewlabel = gtk.Label("Set View:") viewtable.attach(setviewlabel, 0, 1, 1, 2) liststore = gtk.ListStore(gobject.TYPE_STRING) self.viewmenu = gtk.ComboBox(liststore) cell = gtk.CellRendererText() self.viewmenu.pack_start(cell, True) self.viewmenu.add_attribute(cell, 'text', 0) #tooltips.set_tooltip_text(self.viewmenu,"Restore a saved view") # menu items filled in later when saved_views is initialized self.signal = gtklogger.connect(self.viewmenu, 'changed', self.setview) viewtable.attach(self.viewmenu, 1, 2, 1, 2) self.SetDefaultViews() # position information voxelinfoframe = gtk.Frame("Voxel Info") voxelinfoframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(voxelinfoframe) voxelinfobox = gtk.VBox() voxelinfoframe.add(voxelinfobox) voxelinfotable = gtk.Table(rows=3, columns=2) voxelinfobox.pack_start(voxelinfotable) label = gtk.Label('x=') label.set_alignment(1.0, 0.5) voxelinfotable.attach(label, 0, 1, 0, 1, xpadding=5, xoptions=gtk.FILL) self.xtext = gtk.Entry() self.xtext.set_size_request(ndigits * guitop.top().digitsize, -1) voxelinfotable.attach(self.xtext, 1, 2, 0, 1, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) label = gtk.Label('y=') label.set_alignment(1.0, 0.5) voxelinfotable.attach(label, 0, 1, 1, 2, xpadding=5, xoptions=gtk.FILL) self.ytext = gtk.Entry() self.ytext.set_size_request(ndigits * guitop.top().digitsize, -1) voxelinfotable.attach(self.ytext, 1, 2, 1, 2, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL) label = gtk.Label('z=') label.set_alignment(1.0, 0.5) voxelinfotable.attach(label, 0, 1, 2, 3, xpadding=5, xoptions=gtk.FILL) self.ztext = gtk.Entry() self.ztext.set_size_request(ndigits * guitop.top().digitsize, -1) voxelinfotable.attach(self.ztext, 1, 2, 2, 3, xpadding=5, xoptions=gtk.EXPAND | gtk.FILL)
def __init__(self, viewertoolbox): debug.mainthreadTest() toolboxGUI.GfxToolbox.__init__(self, "Viewer", viewertoolbox) mainbox = gtk.VBox() self.gtk.add(mainbox) infoframe = gtk.Frame("Position Information") infoframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(infoframe, fill=0, expand=0) infotable = gtk.Table(columns=3, rows=2) infoframe.add(infotable) pixellabel = gtk.Label("Pixel: ") pixellabel.set_alignment(1.0, 0.5) self.pixel_x = gtk.Entry() gtklogger.setWidgetName(self.pixel_x, "PixelX") self.pixel_x.set_size_request(ndigits*guitop.top().digitsize, -1) self.pixel_x.set_editable(0) self.pixel_y = gtk.Entry() gtklogger.setWidgetName(self.pixel_y, "PixelY") self.pixel_y.set_size_request(ndigits*guitop.top().digitsize, -1) self.pixel_y.set_editable(0) physicallabel = gtk.Label("Physical: ") physicallabel.set_alignment(1.0, 0.5) self.physical_x = gtk.Entry() gtklogger.setWidgetName(self.physical_x, "PhysicalX") self.physical_x.set_size_request(ndigits*guitop.top().digitsize, -1) self.physical_x.set_editable(0) self.physical_y = gtk.Entry() gtklogger.setWidgetName(self.physical_y, "PhysicalY") self.physical_y.set_size_request(ndigits*guitop.top().digitsize, -1) self.physical_y.set_editable(0) infotable.attach(pixellabel, 0,1, 0,1, xpadding=5, ypadding=2, xoptions=0) infotable.attach(self.pixel_x, 1,2, 0,1, xpadding=1, ypadding=2, xoptions=gtk.FILL|gtk.EXPAND) infotable.attach(self.pixel_y, 2,3, 0,1, xpadding=1, ypadding=2, xoptions=gtk.FILL|gtk.EXPAND) infotable.attach(physicallabel, 0,1, 1,2, xpadding=5, ypadding=2, xoptions=0) infotable.attach(self.physical_x, 1,2, 1,2, xpadding=1, ypadding=2, xoptions=gtk.FILL|gtk.EXPAND) infotable.attach(self.physical_y, 2,3, 1,2, xpadding=1, ypadding=2, xoptions=gtk.FILL|gtk.EXPAND) zoomframe = gtk.Frame("Zoom") gtklogger.setWidgetName(zoomframe, "Zoom") zoomframe.set_shadow_type(gtk.SHADOW_IN) mainbox.pack_start(zoomframe, fill=0, expand=0) zoombox = gtk.VBox() zoomframe.add(zoombox) buttonrow = gtk.HBox(homogeneous=1, spacing=2) zoombox.pack_start(buttonrow, expand=0, fill=1, padding=2) inbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_IN, 'In') buttonrow.pack_start(inbutton, expand=0, fill=1) gtklogger.setWidgetName(inbutton, "In") gtklogger.connect(inbutton, 'clicked', self.inCB) outbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_OUT, 'Out') buttonrow.pack_start(outbutton, expand=0, fill=1) gtklogger.setWidgetName(outbutton, "Out") gtklogger.connect(outbutton, 'clicked', self.outCB) fillbutton = gtkutils.StockButton(gtk.STOCK_ZOOM_FIT, 'Fill') buttonrow.pack_start(fillbutton, expand=0, fill=1) gtklogger.setWidgetName(fillbutton, "Fill") gtklogger.connect(fillbutton, 'clicked', self.fillCB) factorrow = gtk.HBox() zoombox.pack_start(factorrow, expand=0, fill=0, padding=2) factorrow.pack_start(gtk.Label("Zoom Factor: "), expand=0, fill=0) self.zoomfactor = gtk.Entry() self.zoomfactor.set_editable(1) self.zoomfactor.set_size_request(ndigits*guitop.top().digitsize, -1) gtklogger.setWidgetName(self.zoomfactor, "Factor") self.zfactorsignal = gtklogger.connect_passive(self.zoomfactor,"changed") factorrow.pack_start(self.zoomfactor, expand=1, fill=1) zoombox.pack_start(gtk.HSeparator(), fill=0, expand=0, padding=2) label0 = gtk.Label("Shift+Click: Zoom in\nCtrl+Click: Zoom out") label0.set_pattern(" _______\n ________\n") label0.set_justify(gtk.JUSTIFY_LEFT) zoombox.pack_start(label0, fill=0, expand=0, padding=2) align = gtk.Alignment(xalign=0.5) mainbox.pack_end(align, expand=0, fill=0, padding=2) canvas_info = gtkutils.StockButton(gtk.STOCK_DIALOG_INFO, "Canvas Info") gtklogger.setWidgetName(canvas_info, "Info") gtklogger.connect(canvas_info, "clicked", self.canvas_infoCB) tooltips.set_tooltip_text(canvas_info, "Display canvas information in the message window.") align.add(canvas_info) self.currentZFactor = self.gfxwindow().zoomFactor() switchboard.requestCallbackMain("zoom factor changed", self.zfactorCB) # Make sure that the Zoom commands in the graphics windows # Settings menu use an up-to-date zoom factor. self.gfxwindow().menu.Settings.Zoom.In.add_gui_callback( self.wrapMenuZoom) self.gfxwindow().menu.Settings.Zoom.Out.add_gui_callback( self.wrapMenuZoom)