def redraw(self): self.data.sort(self.sortfn) rows = len(self.data) cols = 0 if rows > 0: cols = len(self.data[0]) self.grid.resize(rows, cols) self.header.resize(1, cols) cf = self.grid.getCellFormatter() for (nrow, row) in enumerate(self.data): for (ncol, item) in enumerate(row): self.grid.setHTML(nrow, ncol, str(item)) cf.setWidth(nrow, ncol, "200px") cf = self.header.getCellFormatter() self.sortbuttons = [] for ncol in range(cols): sb = Button("sort col %d" % ncol) sb.addClickListener(self) self.header.setWidget(0, ncol, sb) cf.setWidth(0, ncol, "200px") self.sortbuttons.append(sb)
class YChanger (HorizontalPanel): def __init__(self, chart): self.chart = chart HorizontalPanel.__init__(self) # y-changing, x,y coordinate displaying, widget self.incrementY = Button("Increment Y") self.coordinates = HTML(""); # x,y of selected point self.decrementY = Button("Decrement Y") self.incrementY.addClickListener(self) self.decrementY.addClickListener(self) self.add(self.incrementY) self.add(self.coordinates) self.add(self.decrementY) def onClick(self, sender): if sender == self.incrementY: self.chart.getTouchedPoint().setY( self.chart.getTouchedPoint().getY() + 1) else: self.chart.getTouchedPoint().setY( self.chart.getTouchedPoint().getY() - 1) self.chart.update() # The 2 HoverUpdateable interface methods: def hoverCleanup(self, hoveredAwayFrom): pass def hoverUpdate(self, hoveredOver): # update (x,y) display when they click point self.coordinates.setHTML(hoveredOver.getHovertext())
class TestRect: def onModuleLoad(self): self.r = Rect(0.0, 0.0) self.xbox = TextBox() self.ybox = TextBox() self.addbutton = Button("Click to add x and y to Rectangle") self.addbutton.addClickListener(self) self.xbox.setText("2") self.ybox.setText("5") RootPanel().add(HTML("X Value:")) RootPanel().add(self.xbox) RootPanel().add(HTML("Y Value:")) RootPanel().add(self.ybox) RootPanel().add(self.addbutton) RootPanel().add(HTML("Current value: %d %d" % ( self.r.get_x(), self.r.get_y()))) def onClick(self, sender): x = int(self.xbox.getText()) y = int(self.ybox.getText()) r = Rect(x, y) self.r.add(r) RootPanel().add(HTML("New value: %d" % ( self.r.get_x()))) RootPanel().add(HTML("New value: %d" % ( self.r.get_y()))) RootPanel().add(HTML("New value: %d %d" % ( self.r.get_x(), self.r.get_y()))) RootPanel().add(HTML("New Area: %d" % self.r.area()))
class YChanger(HorizontalPanel): def __init__(self, chart): self.chart = chart HorizontalPanel.__init__(self) # y-changing, x,y coordinate displaying, widget self.incrementY = Button("Increment Y") self.coordinates = HTML("") # x,y of selected point self.decrementY = Button("Decrement Y") self.incrementY.addClickListener(self) self.decrementY.addClickListener(self) self.add(self.incrementY) self.add(self.coordinates) self.add(self.decrementY) def onClick(self, sender): if sender == self.incrementY: self.chart.getTouchedPoint().setY( self.chart.getTouchedPoint().getY() + 1) else: self.chart.getTouchedPoint().setY( self.chart.getTouchedPoint().getY() - 1) self.chart.update() # The 2 HoverUpdateable interface methods: def hoverCleanup(self, hoveredAwayFrom): pass def hoverUpdate(self, hoveredOver): # update (x,y) display when they click point self.coordinates.setHTML(hoveredOver.getHovertext())
def __init__(self): DockPanel.__init__(self) self.setSize('100%', '100%') self.geocoder = Geocoder() # widgets topPanel = HorizontalPanel() self.add(topPanel, DockPanel.NORTH) self.address = TextBox() self.address.setText("Sydney, NSW") self.address.addChangeListener(self.codeAddress) topPanel.add(self.address) button = Button("Geocode") button.addClickListener(self.codeAddress) topPanel.add(button) # now, the map mapPanel = SimplePanel() mapPanel.setSize('600', '400') self.add(mapPanel, DockPanel.CENTER) options = MapOptions(zoom=8, center=LatLng(-34.397, 150.644), mapTypeId=MapTypeId.ROADMAP) self.map = Map(mapPanel.getElement(), options)
class TestDict: def onModuleLoad(self): self.r = WrapperDict() self.kbox = TextBox() self.addbutton = Button( "Click to look up key value (hello or goodbye)") self.addbutton.addClickListener(self) self.kbox.setText("hello") # default to make life easier RootPanel().add(HTML("Key:")) RootPanel().add(self.kbox) RootPanel().add(self.addbutton) def display_value(self): key = self.kbox.getText() RootPanel().add(HTML("Value using python:")) RootPanel().add(HTML(self.r.python_get_value(key))) RootPanel().add(HTML("Value using javascript:")) RootPanel().add(HTML(self.r.javascript_get_value(key))) def onClick(self, sender): self.display_value()
class TestDict: def onModuleLoad(self): self.r = WrapperDict() self.kbox = TextBox() self.addbutton = Button("Click to look up key value (hello or goodbye)") self.addbutton.addClickListener(self) self.kbox.setText("hello") # default to make life easier RootPanel().add(HTML("Key:")) RootPanel().add(self.kbox) RootPanel().add(self.addbutton) def display_value(self): key = self.kbox.getText() RootPanel().add(HTML("Value using python:" )) RootPanel().add(HTML(self.r.python_get_value(key))) RootPanel().add(HTML("Value using javascript:" )) RootPanel().add(HTML(self.r.javascript_get_value(key))) def onClick(self, sender): self.display_value()
def make_panel(self): message = Label( 'The configuration has been changed.\n' 'You must apply the changes in order for them to take effect.') DOM.setStyleAttribute(message.getElement(), "whiteSpace", 'pre') msgbox = Grid(1, 2, StyleName='changes') msgbox.setWidget(0, 0, Image('icons/exclam.png')) msgbox.setWidget(0, 1, message) msgbox.getCellFormatter().setStyleName(0, 0, 'changes-image') msgbox.getCellFormatter().setStyleName(0, 1, 'changes-text') button = Button('apply changes') button.addClickListener(self.apply_clicked) self.changes = VerticalPanel() self.changes.setHorizontalAlignment('right') self.changes.setVisible(False) self.changes.add(msgbox) self.changes.add(button) panel = VerticalPanel() panel.setSpacing(10) panel.add(self.table) panel.add(self.status) panel.add(self.changes) return panel
def createTextThing(self, textBox): p = HorizontalPanel() p.setSpacing(4) p.add(textBox) echo = HTML() select_all = Button("select all") p.add(select_all) p.add(echo) listener=TextBoxListener(self, textBox, echo, select_all) select_all.addClickListener(listener) textBox.addKeyboardListener(listener) textBox.addClickListener(listener) return p
def createTextThing(self, textBox): p = HorizontalPanel() p.setSpacing(4) p.add(textBox) echo = HTML() select_all = Button("select all") p.add(select_all) p.add(echo) listener = TextBoxListener(self, textBox, echo, select_all) select_all.addClickListener(listener) textBox.addKeyboardListener(listener) textBox.addClickListener(listener) return p
def make_panel(self): duration = ListBox() duration.setVisibleItemCount(1) choices = [ 1, 2, 3, 4, 5, 7, 10, 15, 20, 25, 30, 40, 50, 60 ] for seconds in choices: duration.addItem( '%ds' % seconds if seconds < 60 else '%dm' % (seconds / 60), seconds) duration.setSelectedIndex(2) button = Button('test') handler = TestHandler(duration) button.addClickListener(handler.func) panel = HorizontalPanel() panel.add(duration) panel.add(button) return panel
def onModuleLoad(self): self.panel = VerticalPanel() self.panel.setSpacing(10) RootPanel().add(self.panel) self.swfUpload = self.getSWFUpload() self.panel.add(self.swfUpload) self.fileids = [] self.queue = VerticalPanel() self.panel.add(self.queue) startButton = Button('Start Upload') startButton.addClickListener(getattr(self, 'onStartUpload')) self.panel.add(startButton) self.progress = Label() self.panel.add(self.progress)
class DbTest(): def __init__(self): self.tb = TextBox() self.b = Button("add") self.g = Grid() self.g.resize(4, 2) RootPanel().add(HTML("Add Phrase. Press Button.")) RootPanel().add(self.tb) RootPanel().add(self.b) RootPanel().add(self.g) self.b.addClickListener(self) try: self.db = Factory.createDatabase() self.db.open('database-demo') self.db.execute('create table if not exists Demo' + ' (Phrase varchar(255), Timestamp int)') except: alert( "Could not create database.\nDo you have the google gears extension installed?" ) def onClick(self, sender): phrase = self.tb.getText() currTime = time() self.db.execute('insert into Demo values (?, ?)', phrase, currTime) rs = self.db.execute('select * from Demo order by Timestamp desc') index = 0 while rs.isValidRow(): if index < 4: self.g.setHTML(index, 0, rs.field(0)) self.g.setHTML(index, 1, rs.field(1)) else: self.db.execute('delete from Demo where Timestamp=?', rs.field(1)) index += 1 rs.next() rs.close()
class DbTest(): def __init__(self): self.tb = TextBox() self.b = Button("add") self.g = Grid() self.g.resize(4, 2) RootPanel().add(HTML("Add Phrase. Press Button.")) RootPanel().add(self.tb) RootPanel().add(self.b) RootPanel().add(self.g) self.b.addClickListener(self) try: self.db = Factory.createDatabase() self.db.open('database-demo') self.db.execute('create table if not exists Demo' + ' (Phrase varchar(255), Timestamp int)') except ex: log("could not create database" + str(ex)) def onClick(self, sender): phrase = self.tb.getText() currTime = time() self.db.execute('insert into Demo values (?, ?)', phrase, currTime); rs = self.db.execute('select * from Demo order by Timestamp desc'); index = 0 while rs.isValidRow(): if index <4: self.g.setHTML(index, 0, rs.field(0)) self.g.setHTML(index, 1, rs.field(1)) else: self.db.execute('delete from Demo where Timestamp=?', rs.field(1)); index += 1 rs.next() rs.close()
def drawControl(container): bar = HorizontalPanel(ID='aur-search-bar', VerticalAlignment='middle') adv = HorizontalPanel(ID='aur-search-advanced', Visible=False) adv_toggle = Hyperlink(Text='Advanced', StyleName='aur-link-stateless aur-search-bar-advanced', TargetHistoryToken=History.getToken()) query = TextBox(Text='enter search term...', StyleName='aur-search-bar-query') go = Button(HTML='Go', StyleName='aur-search-bar-submit') container.add(bar) container.add(adv) # slight workaround to make sure the 'Advanced' toggle doesn't change the page def updateAdvToken(token): adv_toggle.setTargetHistoryToken(token) obj = object() setattr(obj, 'onHistoryChanged', updateAdvToken) History.addHistoryListener(obj) # clickListener to toggle the advanced section def toggleAdv(sender): if adv.isVisible(): adv.setVisible(False) query.setEnabled(True) adv_toggle.setText('Advanced') else: adv.setVisible(True) query.setEnabled(False) adv_toggle.setText('Basic') adv_toggle.addClickListener(toggleAdv) def doGo(): History.newItem('/package/search') go.addClickListener(doGo) bar.add(Label('Search Criteria', StyleName='aur-search-bar-label')) bar.add(query) bar.add(go) bar.add(Button(HTML='Orphans', StyleName='aur-search-bar-submit')) bar.add(adv_toggle) drawAdvanced(adv)
class HomePanel(AbsolutePanel): def __init__(self, parent): AbsolutePanel.__init__(self) self.home_header = Label("Blogjamas", StyleName="header_label") self.write_button = Button("Write a Post") self.edit_hidden_button = Button("", StyleName="hidden_button") self.delete_hidden_button = Button("", StyleName="hidden_button") self.add(self.home_header) self.add(self.write_button) self.add(self.edit_hidden_button) self.add(self.delete_hidden_button) def update_posts(self, posts): self.contents = VerticalPanel(Spacing=1) for i in range(len(posts)): self.divider = HTML("----------------------------------------------------") self.contents.add(self.divider) self.post_title = Label(posts[i].title, StyleName="title_label") self.contents.add(self.post_title) self.post_content = Label(posts[i].content, StyleName="content_label") self.contents.add(self.post_content) self.edit_button = Button("Edit") self.edit_button.setID("edit_" + posts[i].post_id) self.edit_button.addClickListener(self.show_edit_box) self.contents.add(self.edit_button) self.delete_button = Button("Delete") self.delete_button.setID("delete_" + posts[i].post_id) self.delete_button.addClickListener(self.delete_post) self.contents.add(self.delete_button) self.add(self.contents) def show_edit_box(self, sender): self.edit_hidden_button.setID(sender.getID()) self.edit_hidden_button.click(self) def delete_post(self, sender): self.delete_hidden_button.setID(sender.getID()) self.delete_hidden_button.click(self)
def add_button ( self, action, bbox, method=None, enabled=True, name=None ): """ Creates a button. """ ui = self.ui if ((action.defined_when != '') and (not ui.eval_when( action.defined_when ))): return None if name is None: name = action.name id = action.id button = Button(name) bbox.add(button) # button.setAutoDefault(False) button.setEnabled(enabled) if (method is None) or (action.enabled_when != '') or (id != ''): editor = ButtonEditor( ui = ui, action = action, control = button ) if id != '': ui.info.bind( id, editor ) if action.visible_when != '': ui.add_visible( action.visible_when, editor ) if action.enabled_when != '': ui.add_enabled( action.enabled_when, editor ) if method is None: method = editor.perform if method is not None: button.addClickListener(method) if action.tooltip != '': # button.setToolTip(action.tooltip) print "Tooltips for buttons are not implemeted," return button
class TestRect: def onModuleLoad(self): self.r = Rect(0.0, 0.0) self.xbox = TextBox() self.ybox = TextBox() self.addbutton = Button("Click to add x and y to Rectangle") self.addbutton.addClickListener(self) self.xbox.setText("2") self.ybox.setText("5") RootPanel().add(HTML("X Value:")) RootPanel().add(self.xbox) RootPanel().add(HTML("Y Value:")) RootPanel().add(self.ybox) RootPanel().add(self.addbutton) RootPanel().add( HTML("Current value: %d %d" % (self.r.get_x(), self.r.get_y()))) def onClick(self, sender): x = int(self.xbox.getText()) y = int(self.ybox.getText()) r = Rect(x, y) self.r.add(r) RootPanel().add(HTML("New value: %d" % (self.r.get_x()))) RootPanel().add(HTML("New value: %d" % (self.r.get_y()))) RootPanel().add( HTML("New value: %d %d" % (self.r.get_x(), self.r.get_y()))) RootPanel().add(HTML("New Area: %d" % self.r.area()))
class Client: def onModuleLoad(self): # Window.setTitle("CBC Test Stand") StyleSheetCssFile("styleSheet.css") self.TEXT_WAITING = "Waiting for response..." self.TEXT_ERROR = "Server Error" self.status = Label() # This is the remote service self.I2CPanel = I2CPanel() self.SCurveRunPanel = SCurveRunPanel() self.OccupancyCheckPanel = OccupancyCheckPanel() self.CalibrateChannelTrimsPanel = CalibrateChannelTrimsPanel() # mainPanel will have all of the working stuff in it self.mainPanel = DockPanel() # self.mainPanel.setSpacing(10) titleBar = HorizontalPanel() titleBar.add(HTML(r"CBC Test Stand (v1.1)", StyleName="titleStyle")) self.stopTakingDataButton = Button("Stop taking data") self.stopTakingDataButton.addClickListener(self) self.dataTakingPercentage = HTML("0%") self.dataTakingStatus = HTML("Initiating...") titleBar.add(self.dataTakingPercentage) titleBar.add(self.dataTakingStatus) titleBar.add(self.stopTakingDataButton) titleBar.setCellHorizontalAlignment(self.dataTakingStatus, HasHorizontalAlignment.ALIGN_RIGHT) titleBar.setCellHorizontalAlignment(self.dataTakingPercentage, HasHorizontalAlignment.ALIGN_RIGHT) titleBar.setCellHorizontalAlignment(self.stopTakingDataButton, HasHorizontalAlignment.ALIGN_RIGHT) titleBar.setWidth("100%") self.mainPanel.add(titleBar, DockPanel.NORTH) selectionPanel = VerticalPanel() # Register to get updates about the status of data taking, so that # I can update the information in the title bar self.dataRunManager = DataRunManager.instance() self.dataRunManager.registerEventHandler(self) self.activePanelButton = None self.activePanel = None self.registersButton = Label("I2C Registers", StyleName="areaStyle") self.occupanciesButton = Label("Test Occupancies", StyleName="areaStyle") self.scurveButton = Label("S-Curve Run", StyleName="areaStyle") self.calibrateTrimsButton = Label("Calibrate Trims", StyleName="areaStyle") self.registersButton.addClickListener(self) self.occupanciesButton.addClickListener(self) self.scurveButton.addClickListener(self) self.calibrateTrimsButton.addClickListener(self) selectionPanel.add(self.registersButton) selectionPanel.add(self.occupanciesButton) selectionPanel.add(self.scurveButton) selectionPanel.add(self.calibrateTrimsButton) self.mainPanel.add(selectionPanel, DockPanel.WEST) self.mainPanel.add(self.status, DockPanel.SOUTH) RootPanel().add(self.mainPanel) self.setNewMainPanel(self.registersButton) def onDataTakingEvent(self, eventCode, details): """ Method that receives updates from DataRunManager """ if eventCode == DataRunManager.DataTakingStartedEvent: self.stopTakingDataButton.setEnabled(True) self.dataTakingPercentage.setText("0%") self.dataTakingStatus.setText("Starting run...") elif eventCode == DataRunManager.DataTakingFinishedEvent: self.stopTakingDataButton.setEnabled(False) self.dataTakingPercentage.setText("") self.dataTakingStatus.setText("Not taking data") elif eventCode == DataRunManager.DataTakingStatusEvent: self.stopTakingDataButton.setEnabled(True) self.dataTakingPercentage.setText("%3d%%" % int(details["fractionComplete"] * 100 + 0.5)) self.dataTakingStatus.setText(details["statusString"]) def onClick(self, sender): # (data, response_class): if the latter is 'self', then # the response is handled by the self.onRemoteResponse() method try: if sender == self.stopTakingDataButton: self.dataRunManager.stopTakingData() else: # I don't have any other buttons so it must be a panel change self.setNewMainPanel(sender) except Exception as error: self.status.setText("Client exception was thrown: '" + str(error.__class__) + "'='" + str(error) + "'") def setNewMainPanel(self, panelButton): if panelButton == self.activePanelButton: return # already the active panel so no need to do anything # Remove the "selected" style from the current button if self.activePanelButton != None: self.activePanelButton.setStyleName("areaStyle") # Set the "selected" style on the new one self.activePanelButton = panelButton self.activePanelButton.setStyleName("selectedAreaStyle") # Clear the main panel if self.activePanel != None: self.mainPanel.remove(self.activePanel.getPanel()) # Figure out what the new main panel should be if panelButton == self.registersButton: self.activePanel = self.I2CPanel elif panelButton == self.scurveButton: self.activePanel = self.SCurveRunPanel elif panelButton == self.occupanciesButton: self.activePanel = self.OccupancyCheckPanel elif panelButton == self.calibrateTrimsButton: self.activePanel = self.CalibrateChannelTrimsPanel # Set the new main panel self.activePanel.getPanel().setStyleName("selectedAreaStyle") self.activePanel.getPanel().setWidth("100%") self.mainPanel.add(self.activePanel.getPanel(), DockPanel.CENTER) def onRemoteResponse(self, response, request_info): self.status.setText(response) def onRemoteError(self, code, message, request_info): ErrorMessage("Unable to contact server")
class SCurveRunPanel : class onClickListener : def __init__(self, panel) : self._ClickPanel=panel def onRemoteResponse(self, response, request_info): #self._ClickPanel.launchButton.setEnabled(False) for buttonName in self._ClickPanel.controlValueEntries: pass #self._ClickPanel.controlValueEntries[buttonName].setText(response[buttonName]) #self._ClickPanel.controlValueEntries["RangeHi"].setText(response.keys()[1]) #self._ClickPanel.launchButton.setEnabled(True) def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class controlSCurveValueListener : def __init__(self, panel) : self._controlPanel=panel #self._controlPanel.launchButton.setEnabled(False) #self._controlPanel.echoSelection() def onRemoteResponse(self, response, request_info): self._controlPanel.launchButton.setEnabled(False) def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class DoNothingListener : """ A class to listen for the response to any calls where I don't care about the result. Later on I'll put in a popup if there's a message. """ def onRemoteResponse(self, response, request_info): # Don't actually want to do anything pass def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server: "+str(message) ) class SaveHistogramsListener : def __init__( self, buttonToEnable ) : self.buttonToEnable=buttonToEnable def onRemoteResponse(self, response, request_info): self.buttonToEnable.setEnabled(True) ErrorMessage( "Histograms saved", messageTitle="Message" ) def onRemoteError(self, code, message, request_info): self.buttonToEnable.setEnabled(True) ErrorMessage( "Unable to contact server: "+str(message) ) class DataTakingStatusListener : def __init__( self, SCurveRunPanelInstance ) : self.parentInstance=SCurveRunPanelInstance def onRemoteResponse(self, response, request_info): self.parentInstance.echo.setText(response["statusString"] ) if response["fractionComplete"]<1: self.parentInstance.launchButton.setEnabled(False) else: self.parentInstance.launchButton.setEnabled(True) self.parentInstance.echo.setText("No data taking") def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server: "+str(message) ) def __init__( self ) : # This is the service that will be used to communicate with the DAQ software self.rpcService = GlibRPCService.instance() self.dataRunManager = DataRunManager.instance() self.mainPanel = VerticalPanel() self.mainPanel.setSpacing(15) self.controlValueEntries={} #controls the parameters of the s-curve #self.graphCanvas=GraphCanvas(self) #self.rpcService.getSCurveValues( ) self.mainSettings=VerticalPanel("Control Settings") self.startButton=VerticalPanel("Run Button") self.canvasPanel=VerticalPanel("Canvas") self.mainSettings.add(self.createControlPanel(["RangeLo","RangeHi","Steps"])) self.echo=Label() # A good print screen method self.launchButton=Button("Launch Now") self.launchButton.addClickListener(self) self.launchButton.setEnabled(True) saveHistogramsPanel=HorizontalPanel() self.saveHistogramsButton=Button("Save histograms") self.saveHistogramsButton.setEnabled(False) # Disable this button until data has been taken self.saveHistogramsButton.addClickListener(self) self.saveHistogramsFilename=TextBox("Filename") self.saveHistogramsFilename.setText("/tmp/scurveHistograms.root") self.saveHistogramsFilename.setVisibleLength(50) saveHistogramsPanel.add( self.saveHistogramsButton ) saveHistogramsPanel.add( self.saveHistogramsFilename ) self.mainPanel.add(self.mainSettings) self.mainPanel.add(self.startButton) self.mainPanel.add(self.launchButton) self.mainPanel.add(self.echo) self.mainPanel.add(saveHistogramsPanel) histogramDisplay=DisplayHistogramsPanel() self.mainPanel.add( HTML( '<br><b>Results:</b> (note that selecting a lot of channels can take a very long time)') ) self.mainPanel.add( histogramDisplay.getPanel() ) self.dataRunManager.registerEventHandler( self ) def onDataTakingEvent( self, eventCode, details ) : """ Method that receives updates from DataRunManager """ if eventCode==DataRunManager.DataTakingStartedEvent : self.echo.setText("Taking data... ") self.launchButton.setEnabled(False) elif eventCode==DataRunManager.DataTakingFinishedEvent : self.echo.setText("Data taking finished") self.launchButton.setEnabled(True) self.saveHistogramsButton.setEnabled(True) elif eventCode==DataRunManager.DataTakingStatusEvent : self.echo.setText("%3d%% - "%int(details['fractionComplete']*100+0.5)+details['statusString'] ) def onChange( self, sender ) : pass def onClick(self, sender): self.msg = {"RangeLo":50, "RangeHi" :150, "Steps":1, "FileName":"test.png"} if sender==self.launchButton : self.echo.setText("Initiating run") rangeHigh=int(self.rangeHighBox.getText()) rangeLow=int(self.rangeLowBox.getText()) stepSize=int(self.stepSizeBox.getText()) self.dataRunManager.startSCurveRun( range(rangeLow,rangeHigh,stepSize) ) #self.rpcService.startSCurveRun(None, SCurveRunPanel.DoNothingListener() ) if sender==self.saveHistogramsButton : self.saveHistogramsButton.setEnabled(False) self.rpcService.saveHistograms( self.saveHistogramsFilename.getText(), SCurveRunPanel.SaveHistogramsListener(self.saveHistogramsButton) ) def updateStatus(self): self.rpcService.getDataTakingStatus( None, SCurveRunPanel.DataTakingStatusListener(self) ) def getPanel(self) : return self.mainPanel def createControlPanel(self, controlNames): flowPanel=FlowPanel() newLabels=[] for buttonName in controlNames: newPanel=HorizontalPanel() newLabels.append(Label(buttonName)) newPanel.add(newLabels[-1]) newTextBox=TextBox() newTextBox.setEnabled(True) newTextBox.setWidth(80) newPanel.add(newTextBox) if buttonName=="RangeLo" : newTextBox.setText("100") # Default values self.rangeLowBox=newTextBox elif buttonName=="RangeHi" : newTextBox.setText("150") self.rangeHighBox=newTextBox elif buttonName=="Steps" : newTextBox.setText("1") self.stepSizeBox=newTextBox elif buttonName=="FileName": newTextBox.setText("TestRun.png") #newTextBox.addChangeListener(self) newTextBox.setTitle(buttonName) self.controlValueEntries[buttonName]=newTextBox flowPanel.add(newPanel) # Set all of the widths of the labels to be the same, so that the boxes line up maxWidth=0 for label in newLabels : # This doesn't work for some reason #if label.getWidth() > maxWidth : maxWidth=label.getWidth() if len(label.getText())*9 > maxWidth : maxWidth=len(label.getText())*9 for label in newLabels : label.setWidth(maxWidth) return flowPanel
class MainPanel(VerticalPanel): CANVAS_WIDTH = 900 CANVAS_HEIGHT = 700 def __init__(self, owner): super(VerticalPanel, self).__init__() self.edgequeue = list() self.owner = owner self.InitialiseScreen() StaticObjectsTask(self.Draw).schedule(5000) #Poll every five seconds def EdgeListener(self, edge): self.edgequeue.append(edge.asDict()) EdgePoster(self.edgequeue).schedule( 1) #Schedule in the future so edges are sent in bulk def InitialiseScreen(self): hpanel = HorizontalPanel() self.add(hpanel) vpanelMenu = VerticalPanel() hpanel.add(vpanelMenu) self.addbutton = Button("Add Triangle") vpanelMenu.add(self.addbutton) self.addbutton.addClickListener(getattr(self, "addtriangle")) self.canvas = GWTCanvas(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) vpanelCanvas = VerticalPanel() self.canvas.setWidth(self.CANVAS_WIDTH) self.canvas.setHeight(self.CANVAS_HEIGHT) hpanel.add(vpanelCanvas) vpanelCanvas.add(self.canvas) self.canvas.addMouseListener(self) self.selecteditem = None self.selectedhandle = None self.mouseisdown = False dc = DocumentCollection.documentcollection DocumentCollection.documentcollection.edgelistener = self.EdgeListener if len(dc.documentsbyclass[model.Drawing.__name__]) == 0: drawing = model.Drawing(None) dc.AddDocumentObject(drawing) EdgePoster([a.asDict() for a in drawing.history.GetAllEdges()]) else: for k, v in dc.documentsbyclass[ model.Drawing.__name__].iteritems(): drawing = v self.drawingid = drawing.id self.Draw() def GetDrawing(self): return DocumentCollection.documentcollection.objectsbyid[ self.drawingid] def sortfn(self, t1, t2): return cmp(t1.z_order, t2.z_order) def GetTrianglesAsList(self): #Return the triangles as an ordinary python list #triangles = [self.drawing.triangles.GetDocument().documentobjects[objid] for objid in self.drawing.triangles] triangles = list() for triangle in self.GetDrawing().triangles: #triangles = self.drawing.GetDocument().documentobjects[objid] triangles.append(triangle) if len(triangles) > 0: triangles.sort(self.sortfn) return triangles def DrawHandle(self, x, y): self.canvas.setFillStyle(Color.RED) self.canvas.beginPath() self.canvas.arc(x, y, 5, 0, math.pi * 2, False) self.canvas.fill() def Draw(self): self.canvas.setFillStyle(Color.WHITE) self.canvas.fillRect(0, 0, self.CANVAS_WIDTH, self.CANVAS_HEIGHT) for t in self.GetTrianglesAsList(): self.canvas.setFillStyle(Color.BLUE) self.canvas.setLineWidth(5) self.canvas.setStrokeStyle(Color.BLACK) self.canvas.setLineWidth(2) self.canvas.beginPath() self.canvas.moveTo(t.x1, t.y1) self.canvas.lineTo(t.x2, t.y2) self.canvas.lineTo(t.x3, t.y3) self.canvas.lineTo(t.x1, t.y1) self.canvas.fill() self.canvas.stroke() if self.selecteditem == t: self.canvas.setLineWidth(1) self.canvas.setStrokeStyle(Color.RED) self.canvas.beginPath() self.canvas.moveTo(t.x1, t.y1) self.canvas.lineTo(t.x2, t.y2) self.canvas.lineTo(t.x3, t.y3) self.canvas.lineTo(t.x1, t.y1) self.canvas.stroke() self.DrawHandle(t.x1, t.y1) self.DrawHandle(t.x2, t.y2) self.DrawHandle(t.x3, t.y3) def addtriangle(self, sender): left_margin = 50 triangle_spacing = 150 drawing = self.GetDrawing() c = len(drawing.triangles) posx = left_margin + c % ((self.CANVAS_WIDTH - left_margin) // triangle_spacing) * triangle_spacing posy = c // ((self.CANVAS_WIDTH - left_margin) // triangle_spacing) * triangle_spacing t = model.Triangle(None) drawing.triangles.add(t) t.z_order = c setattr(t, 'x1', posx) setattr(t, 'y1', posy + 50) setattr(t, 'x2', posx + 100) setattr(t, 'y2', posy + 100) setattr(t, 'x3', posx + 50) setattr(t, 'y3', posy + 150) self.Draw() def onMouseDown(self, sender, x, y): self.mouseisdown = True if self.selecteditem is not None: self.selectedhandle = None if HandleSelected(x, y, self.selecteditem.x1, self.selecteditem.y1): self.selectedhandle = 1 elif HandleSelected(x, y, self.selecteditem.x2, self.selecteditem.y2): self.selectedhandle = 2 elif HandleSelected(x, y, self.selecteditem.x3, self.selecteditem.y3): self.selectedhandle = 3 if self.selectedhandle is None: self.selecteditem = self.FindTriangle(x, y) if self.selecteditem is None and self.selectedhandle is None: self.selectedhandle = None if self.selecteditem is not None: self.selecteditem.changessuspended = True self.Draw() self.lastx = x self.lasty = y def onMouseMove(self, sender, x, y): if self.selecteditem is not None and self.mouseisdown: diffx = x - self.lastx diffy = y - self.lasty t = self.selecteditem if self.selectedhandle is None: setattr(t, 'x1', t.x1 + diffx) setattr(t, 'y1', t.y1 + diffy) setattr(t, 'x2', t.x2 + diffx) setattr(t, 'y2', t.y2 + diffy) setattr(t, 'x3', t.x3 + diffx) setattr(t, 'y3', t.y3 + diffy) elif self.selectedhandle == 1: setattr(t, 'x1', t.x1 + diffx) setattr(t, 'y1', t.y1 + diffy) elif self.selectedhandle == 2: setattr(t, 'x2', t.x2 + diffx) setattr(t, 'y2', t.y2 + diffy) elif self.selectedhandle == 3: setattr(t, 'x3', t.x3 + diffx) setattr(t, 'y3', t.y3 + diffy) self.lastx = x self.lasty = y self.Draw() def onMouseUp(self, sender, x, y): if self.mouseisdown and self.selecteditem: t = self.selecteditem self.selecteditem.changessuspended = False setattr(t, 'x1', t.x1) setattr(t, 'y1', t.y1) setattr(t, 'x2', t.x2) setattr(t, 'y2', t.y2) setattr(t, 'x3', t.x3) setattr(t, 'y3', t.y3) self.mouseisdown = False def onMouseEnter(self, sender, x, y): pass def onMouseLeave(self, sender, x, y): pass def FindTriangle(self, x, y): pt = Point(x, y) for t in self.GetTrianglesAsList(): if PointInTriangle(pt, t): return t return None
class TestrunTimeDeltas(GChart): """ Draws a stacked bar chart of the time deltas for a testrun The central datastructure for the testrun_dts is:- @rtype: A list of [C{tuple} of (C{str}, [C{list} of [C{list} of C{float}]])] @rparam: A tuple of the testrun_id and the time deltas for all the steps in the testrun """ COLORS = ['#a5cee3', '#1f78b3', '#b2de89', '#fcbf6f','#fb9a99', '#693d9a'] STATE_COLORS = {None : '#FFFFFF', '0' : '#FFA500', '1' : '#FFA500', '2' : '#008000', '3' : '#FF0000', '4' : '#FF0000'} WIDTH = 600 SIZE = 220 MARGIN = 7 MAX_X_LABEL_LENGTH = 6 CHUNK_SIZE = 20 BAR_WIDTH = 15 Y_AXIS_SCALING = [1, 2, 3, 5, 7] def __init__(self): GChart.__init__(self) self.first = True self._steps = None self._end_step = None self._testrun_states = None self._timedeltas = None self._no_of_runs = None DEVICE_GROUP = None # Fixme self.remote = DataService() self.remote.get_total_no_of_testruns(DEVICE_GROUP, self) self.remote.get_event_sequence(self) # self.backButton = Button("<b><<</b>") self.backButton.addClickListener(self.onBack) self.forwardButton = Button("<b>>></b>") self.forwardButton.addClickListener(self.onForward) self.setChartFootnotes("") ############################## # SCALING ############################## def _get_longest_time(self, testrun_dts): """ @type: See class docstring @param: The Testrun timedeltas for this `chunk` @rtype: C{int} @rparam: The longest time taken for this chunk of runs """ longest_time = 0 for testrun_idx in range(len(testrun_dts)): testrun_id, all_dts = testrun_dts[testrun_idx] testrun_time = sum([sum(step_dts) for step_dts in all_dts]) longest_time = max(longest_time , testrun_time) return longest_time def _get_y_axis_size(self, longest_time): """ Propose a size for the y axis @rtype: C{int} @rparam: The longest time taken for this chunk of runs """ #FIXME: This is crude and ugly #no doubt gchart provides something better natively candidate = 1 for p in range(4): for scale in self.Y_AXIS_SCALING: candidate = scale*pow(10,p) if candidate > longest_time: break return candidate ############################## # CHART RENDERING ############################## def _vertical_label(self, label, color): """ The label rendered as vertical html @type label: C{str} @rparam label: The x axis label @rtype: C{str} @rparam: Html truncated vertical label """ txt = '<html><center style="background-color:%s">'%(color) label_len = min(len(label), MAX_X_LABEL_LENGTH) for idx in range(label_len): txt += "%s<br>"%(label[idx]) txt += "</center></html>" return txt def _draw_bar_segment(self, testrun_id, curve, x_pos, step_idx, dts): """ Draws one of the stacked bars @type testrun_id: C{str} @param testrun_id: The testrun id @type curve: L{pyjamas.chart.Curve} @param curve: The bar segment is a curve @type x_pos: C{int} @param x_pos: The position of the segment @type step_idx: C{int} @param step_idx: The index of the `step` in te testrun (for this bar) @type dts: C{list} of C{int} @param dts: The timedeltas for the whole testrun """ symbol = curve.getSymbol() symbol.setSymbolType(SymbolType.BOX_NORTHEAST) symbol.setModelHeight(dts[step_idx]) col = self.COLORS[step_idx] symbol.setBackgroundColor(col) symbol.setBorderColor(col) symbol.setWidth(self.BAR_WIDTH) start_time = sum(dts[:step_idx]) curve.addPoint(x_pos, start_time) self._bar_segment_hover_text(testrun_id, symbol, step_idx, dts) def _bar_segment_hover_text(self, testrun_id, symbol, step_idx, dts): """ The hover text for the bar segment @type testrun_id: C{str} @param testrun_id: The testrun id @type symbol: L{pyjamas.chart.Symbol} @param symbol: The @type step_idx: C{int} @param step_idx: The index of the `step` in te testrun (for this bar) @type dts: C{list} of C{int} @param dts: The timedeltas for the whole testrun """ symbol.setHoverAnnotationSymbolType( SymbolType.ANCHOR_MOUSE_SNAP_TO_Y) symbol.setHoverLocation(AnnotationLocation.SOUTHEAST) start_time = sum(dts[:step_idx]) end_time = sum(dts[:step_idx+1]) step = self._steps[step_idx] ht = "<b>%s</b> <i>%s</i>: %ss-%ss" % (testrun_id, step, start_time, end_time) ht = formatAsHovertext(ht) symbol.setHovertextTemplate(ht) def _render_axes(self, testrun_dts): """ Render the stacked bars @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ x_axis = self.getXAxis() x_axis.clearTicks() x_axis.setTickThickness(0) x_axis.setAxisMin(0) x_axis.setAxisMax(self.SIZE) x_axis.addTick(0, self.backButton) x_axis.addTick(self.SIZE, self.forwardButton) # y_axis = self.getYAxis() y_axis.clearTicks() y_axis.setAxisMin(0) longest_time = self._get_longest_time(testrun_dts) y_max = self._get_y_axis_size(longest_time) y_axis.setAxisMax(y_max) #FIXME y_axis.addTick(y_max, " %s"%(str(y_max))) y_axis.addTick(y_max / 2, " %s"%str(y_max/2)) def _render_bars(self, testrun_dts): """ Render the stacked bars @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ curve_idx = 0 for testrun_idx in range(len(testrun_dts)): testrun_id, all_dts = testrun_dts[testrun_idx] #FIXME: Iterations in testrun steps need rendering dts = [sum(step_dts) for step_dts in all_dts] x_pos = self._bar_x_pos(testrun_idx) for step_idx in range(len(dts)): dt = dts[step_idx] curve = self._get_curve(curve_idx) self._draw_bar_segment(testrun_id, curve, x_pos, step_idx, dts) if step_idx == 0: self._x_labels(testrun_idx, testrun_id) curve_idx += 1 def _render_legend(self): """ Render the legend """ no_of_steps = len(self._steps) for step_idx in range(no_of_steps): curve = self.getCurve(step_idx) curve.setLegendLabel(self._steps[step_idx]) def _x_labels(self, bar_idx, testrun_id): """ Add the labels to the X Axis @type bar_idx: C{int} @param bar_idx: The index of the bar @type testrun_id: C{str} @param testrun_id: The testrun id for the label """ state = self._testrun_states[bar_idx] color = self.STATE_COLORS[state] txt = self._vertical_label(str(testrun_id), color) x_pos = self._label_x_pos(bar_idx) self.getXAxis().addTick(x_pos + 2, txt) def _bar_x_pos(self, bar_idx): """ The position on the X Axis of the bar @type bar_idx: C{int} @param bar_idx: The index of the bar @rtype: C{float} @rparam: The position of the bar """ x_pos = ((bar_idx/20.) * (self.SIZE - self.MARGIN)) + self.MARGIN return x_pos def _label_x_pos(self, bar_idx): """ The position on the X Axis of the bar @type bar_idx: C{int} @param bar_idx: The index of the bar @rtype: C{float} @rparam: The position of the bar """ return self._bar_x_pos(bar_idx) + 1 def _get_curve(self, curve_idx): """ If a curve doesn't exist for the index it creates one otherwise it replaces the existing curve @type curve_idx: C{int} @param curve_idx: The index of the curve @rtype: L{pyjamas.chart.Curve} @rparam: The curve """ try: curve = self.getCurve(curve_idx) curve.clearPoints() curve.invalidate() except: self.addCurve() curve = self.getCurve() return curve def _render(self, testrun_dts): """ Render a stacked barchart for the data @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ self.setChartTitle("<b>Testruns</b>") self.setChartSize(self.WIDTH, self.SIZE) self._render_axes(testrun_dts) self._render_bars(testrun_dts) self._render_legend() ################################### # HANDLERS ################################### def onRemoteError(self, code, message, request_info): RootPanel().add(HTML(message)) if DEBUG: RootPanel().add(HTML(message)) else: Window.alert("Remote Error.") def onRemoteResponse(self, response, request_info): """ Handler for the json HttpResponse """ method_name, args = response if method_name == 'get_event_sequence': self._on_get_event_sequence(args) elif method_name == 'get_timedeltas': self._on_get_timedeltas(args) elif method_name == 'get_total_no_of_testruns': self._on_get_total_no_of_testruns(args) elif method_name == 'get_testrun_states': self._on_get_testrun_states(args) def _on_get_timedeltas(self, timedeltas): """ Handler for `get_timedeltas` @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ testrun_ids = [testrun_id for testrun_id, dts in timedeltas] self.remote.get_testrun_states(testrun_ids, self) self._timedeltas = timedeltas def _on_get_event_sequence(self, event_sequence): """ Handler for `get_event_sequence` @type: C{list} of C{str} @param: The sequence of events corresponding to the timedeltas """ if self._steps is None: self._steps = [] for idx in range(1, len(event_sequence)): step = "%s->%s"%(event_sequence[idx-1], event_sequence[idx]) self._steps.append(step) def _on_get_total_no_of_testruns(self, no_of_runs): """ Handler for `get_total_no_of_testruns` @type: C{int} @param: The total no of runs that have been monitored for the device group selection """ self._no_of_runs = no_of_runs self._end_step = no_of_runs self.remote.get_timedeltas(self._end_step - self.CHUNK_SIZE, self._end_step, -1, DEVICE_GROUP, self) def _on_get_testrun_states(self, states): """ Handler for `get_testrun_states` @type: C{list} of C{str} @param: The states of the queried testruns """ self._testrun_states = states self._render(self._timedeltas) self.update() def onForward(self): """ Forward Click handler """ start = self._end_step - (2 * self.CHUNK_SIZE) start = max(0, start) end = start + self.CHUNK_SIZE self.remote.get_timedeltas(start, end, -1, None, self) self._end_step = end def onBack(self): """ Back Click handler """ end = self._end_step + (2 * self.CHUNK_SIZE) end = min(end, self._no_of_runs) start = end - self.CHUNK_SIZE self.remote.get_timedeltas(start, end, -1, None, self) self._end_step = end
class SoftChordApp: def onModuleLoad(self): """ Gets run when the page is first loaded. Creates the widgets. """ self.remote = DataService() main_layout = VerticalPanel() h_layout = HorizontalPanel() h_layout.setPadding(10) songlist_layout = VerticalPanel() songlist_layout.add(Label("Add New Song:")) self.newSongTextBox = TextBox() self.newSongTextBox.addKeyboardListener(self) songlist_layout.add(self.newSongTextBox) self.addSongButton = Button("Add Song") self.addSongButton.addClickListener(self) songlist_layout.add(self.addSongButton) #songlist_layout.add(Label("Click to Remove:")) self.songListBox = ListBox() self.songListBox.setVisibleItemCount(7) self.songListBox.setWidth("300px") self.songListBox.setHeight("400px") self.songListBox.addClickListener(self) songlist_layout.add(self.songListBox) self.deleteSongButton = Button("Delete") self.deleteSongButton.addClickListener(self) songlist_layout.add(self.deleteSongButton) h_layout.add(songlist_layout) #self.textArea = TextArea() #self.textArea.setCharacterWidth(30) #self.textArea.setVisibleLines(50) #h_layout.add(self.textArea) #self.scrollPanel = ScrollPanel(Size=("400px", "500px")) self.songHtml = HTML("<b>Please select a song in the left table</b>") #self.scrollPanel.add(self.songHtml) #h_layout.add(self.scrollPanel) h_layout.add(self.songHtml) main_layout.add(h_layout) self.status = Label() main_layout.add(self.status) RootPanel().add(main_layout) # Populate the song table: self.remote.getAllSongs(self) def onKeyUp(self, sender, keyCode, modifiers): pass def onKeyDown(self, sender, keyCode, modifiers): pass def onKeyPress(self, sender, keyCode, modifiers): """ This functon handles the onKeyPress event """ if keyCode == KeyboardListener.KEY_ENTER and sender == self.newSongTextBox: id = self.remote.addSong(self.newSongTextBox.getText(), self) self.newSongTextBox.setText("") if id<0: self.status.setText("Server Error or Invalid Response") def onClick(self, sender): """ Gets called when a user clicked in the <sender> widget. Currently deletes the song on which the user clicked. """ if sender == self.songListBox: song_id = self.songListBox.getValue(self.songListBox.getSelectedIndex()) self.status.setText("selected song_id: %s" % song_id) id = self.remote.getSong(song_id, self) if id<0: self.status.setText("Server Error or Invalid Response") elif sender == self.addSongButton: id = self.remote.addSong(self.newSongTextBox.getText(), self) self.newSongTextBox.setText("") if id<0: self.status.setText("Server Error or Invalid Response") elif sender == self.deleteSongButton: # Figure out what song is selected in the table: song_id = self.songListBox.getValue(self.songListBox.getSelectedIndex()) self.status.setText("delete song_id: %s" % song_id) id = self.remote.deleteSong(song_id, self) if id<0: self.status.setText("Server Error or Invalid Response") def onRemoteResponse(self, response, request_info): """ Gets called when the backend (django) sends a packet to us. Populates the song table with all songs in the database. """ self.status.setText("response received") if request_info.method == 'getAllSongs' or request_info.method == 'addSong' or request_info.method == 'deleteSong': self.status.setText(self.status.getText() + " - song list received") self.songListBox.clear() for item in response: song_id, song_num, song_title = item if song_num: song_title = "%i %s" % (song_num, song_title) self.songListBox.addItem(song_title) self.songListBox.setValue(self.songListBox.getItemCount()-1, song_id) elif request_info.method == 'getSong': self.status.setText(self.status.getText() + " - song received") song_obj = songs.Song(response) self.status.setText(self.status.getText() + "; id: %i; num-chords: %i" % (song_obj.id, len(song_obj.chords) ) ) self.songHtml.setHTML(song_obj.getHtml()) #self.textArea.setText(song_obj.text) else: # Unknown response received form the server self.status.setText(self.status.getText() + "none!") def onRemoteError(self, code, errobj, request_info): message = errobj['message'] self.status.setText("Server Error or Invalid Response: ERROR %s - %s" % (code, message))
class TestrunTimeDeltas(GChart): """ Draws a stacked bar chart of the time deltas for a testrun The central datastructure for the testrun_dts is:- @rtype: A list of [C{tuple} of (C{str}, [C{list} of [C{list} of C{float}]])] @rparam: A tuple of the testrun_id and the time deltas for all the steps in the testrun """ COLORS = ['#a5cee3', '#1f78b3', '#b2de89', '#fcbf6f', '#fb9a99', '#693d9a'] STATE_COLORS = { None: '#FFFFFF', '0': '#FFA500', '1': '#FFA500', '2': '#008000', '3': '#FF0000', '4': '#FF0000' } WIDTH = 600 SIZE = 220 MARGIN = 7 MAX_X_LABEL_LENGTH = 6 CHUNK_SIZE = 20 BAR_WIDTH = 15 Y_AXIS_SCALING = [1, 2, 3, 5, 7] def __init__(self): GChart.__init__(self) self.first = True self._steps = None self._end_step = None self._testrun_states = None self._timedeltas = None self._no_of_runs = None DEVICE_GROUP = None # Fixme self.remote = DataService() self.remote.get_total_no_of_testruns(DEVICE_GROUP, self) self.remote.get_event_sequence(self) # self.backButton = Button("<b><<</b>") self.backButton.addClickListener(self.onBack) self.forwardButton = Button("<b>>></b>") self.forwardButton.addClickListener(self.onForward) self.setChartFootnotes("") ############################## # SCALING ############################## def _get_longest_time(self, testrun_dts): """ @type: See class docstring @param: The Testrun timedeltas for this `chunk` @rtype: C{int} @rparam: The longest time taken for this chunk of runs """ longest_time = 0 for testrun_idx in range(len(testrun_dts)): testrun_id, all_dts = testrun_dts[testrun_idx] testrun_time = sum([sum(step_dts) for step_dts in all_dts]) longest_time = max(longest_time, testrun_time) return longest_time def _get_y_axis_size(self, longest_time): """ Propose a size for the y axis @rtype: C{int} @rparam: The longest time taken for this chunk of runs """ #FIXME: This is crude and ugly #no doubt gchart provides something better natively candidate = 1 for p in range(4): for scale in self.Y_AXIS_SCALING: candidate = scale * pow(10, p) if candidate > longest_time: break return candidate ############################## # CHART RENDERING ############################## def _vertical_label(self, label, color): """ The label rendered as vertical html @type label: C{str} @rparam label: The x axis label @rtype: C{str} @rparam: Html truncated vertical label """ txt = '<html><center style="background-color:%s">' % (color) label_len = min(len(label), MAX_X_LABEL_LENGTH) for idx in range(label_len): txt += "%s<br>" % (label[idx]) txt += "</center></html>" return txt def _draw_bar_segment(self, testrun_id, curve, x_pos, step_idx, dts): """ Draws one of the stacked bars @type testrun_id: C{str} @param testrun_id: The testrun id @type curve: L{pyjamas.chart.Curve} @param curve: The bar segment is a curve @type x_pos: C{int} @param x_pos: The position of the segment @type step_idx: C{int} @param step_idx: The index of the `step` in te testrun (for this bar) @type dts: C{list} of C{int} @param dts: The timedeltas for the whole testrun """ symbol = curve.getSymbol() symbol.setSymbolType(SymbolType.BOX_NORTHEAST) symbol.setModelHeight(dts[step_idx]) col = self.COLORS[step_idx] symbol.setBackgroundColor(col) symbol.setBorderColor(col) symbol.setWidth(self.BAR_WIDTH) start_time = sum(dts[:step_idx]) curve.addPoint(x_pos, start_time) self._bar_segment_hover_text(testrun_id, symbol, step_idx, dts) def _bar_segment_hover_text(self, testrun_id, symbol, step_idx, dts): """ The hover text for the bar segment @type testrun_id: C{str} @param testrun_id: The testrun id @type symbol: L{pyjamas.chart.Symbol} @param symbol: The @type step_idx: C{int} @param step_idx: The index of the `step` in te testrun (for this bar) @type dts: C{list} of C{int} @param dts: The timedeltas for the whole testrun """ symbol.setHoverAnnotationSymbolType(SymbolType.ANCHOR_MOUSE_SNAP_TO_Y) symbol.setHoverLocation(AnnotationLocation.SOUTHEAST) start_time = sum(dts[:step_idx]) end_time = sum(dts[:step_idx + 1]) step = self._steps[step_idx] ht = "<b>%s</b> <i>%s</i>: %ss-%ss" % (testrun_id, step, start_time, end_time) ht = formatAsHovertext(ht) symbol.setHovertextTemplate(ht) def _render_axes(self, testrun_dts): """ Render the stacked bars @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ x_axis = self.getXAxis() x_axis.clearTicks() x_axis.setTickThickness(0) x_axis.setAxisMin(0) x_axis.setAxisMax(self.SIZE) x_axis.addTick(0, self.backButton) x_axis.addTick(self.SIZE, self.forwardButton) # y_axis = self.getYAxis() y_axis.clearTicks() y_axis.setAxisMin(0) longest_time = self._get_longest_time(testrun_dts) y_max = self._get_y_axis_size(longest_time) y_axis.setAxisMax(y_max) #FIXME y_axis.addTick(y_max, " %s" % (str(y_max))) y_axis.addTick(y_max / 2, " %s" % str(y_max / 2)) def _render_bars(self, testrun_dts): """ Render the stacked bars @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ curve_idx = 0 for testrun_idx in range(len(testrun_dts)): testrun_id, all_dts = testrun_dts[testrun_idx] #FIXME: Iterations in testrun steps need rendering dts = [sum(step_dts) for step_dts in all_dts] x_pos = self._bar_x_pos(testrun_idx) for step_idx in range(len(dts)): dt = dts[step_idx] curve = self._get_curve(curve_idx) self._draw_bar_segment(testrun_id, curve, x_pos, step_idx, dts) if step_idx == 0: self._x_labels(testrun_idx, testrun_id) curve_idx += 1 def _render_legend(self): """ Render the legend """ no_of_steps = len(self._steps) for step_idx in range(no_of_steps): curve = self.getCurve(step_idx) curve.setLegendLabel(self._steps[step_idx]) def _x_labels(self, bar_idx, testrun_id): """ Add the labels to the X Axis @type bar_idx: C{int} @param bar_idx: The index of the bar @type testrun_id: C{str} @param testrun_id: The testrun id for the label """ state = self._testrun_states[bar_idx] color = self.STATE_COLORS[state] txt = self._vertical_label(str(testrun_id), color) x_pos = self._label_x_pos(bar_idx) self.getXAxis().addTick(x_pos + 2, txt) def _bar_x_pos(self, bar_idx): """ The position on the X Axis of the bar @type bar_idx: C{int} @param bar_idx: The index of the bar @rtype: C{float} @rparam: The position of the bar """ x_pos = ((bar_idx / 20.) * (self.SIZE - self.MARGIN)) + self.MARGIN return x_pos def _label_x_pos(self, bar_idx): """ The position on the X Axis of the bar @type bar_idx: C{int} @param bar_idx: The index of the bar @rtype: C{float} @rparam: The position of the bar """ return self._bar_x_pos(bar_idx) + 1 def _get_curve(self, curve_idx): """ If a curve doesn't exist for the index it creates one otherwise it replaces the existing curve @type curve_idx: C{int} @param curve_idx: The index of the curve @rtype: L{pyjamas.chart.Curve} @rparam: The curve """ try: curve = self.getCurve(curve_idx) curve.clearPoints() curve.invalidate() except: self.addCurve() curve = self.getCurve() return curve def _render(self, testrun_dts): """ Render a stacked barchart for the data @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ self.setChartTitle("<b>Testruns</b>") self.setChartSize(self.WIDTH, self.SIZE) self._render_axes(testrun_dts) self._render_bars(testrun_dts) self._render_legend() ################################### # HANDLERS ################################### def onRemoteError(self, code, message, request_info): RootPanel().add(HTML(message)) if DEBUG: RootPanel().add(HTML(message)) else: Window.alert("Remote Error.") def onRemoteResponse(self, response, request_info): """ Handler for the json HttpResponse """ method_name, args = response if method_name == 'get_event_sequence': self._on_get_event_sequence(args) elif method_name == 'get_timedeltas': self._on_get_timedeltas(args) elif method_name == 'get_total_no_of_testruns': self._on_get_total_no_of_testruns(args) elif method_name == 'get_testrun_states': self._on_get_testrun_states(args) def _on_get_timedeltas(self, timedeltas): """ Handler for `get_timedeltas` @type: See class docstring @param: The Testrun timedeltas for this `chunk` """ testrun_ids = [testrun_id for testrun_id, dts in timedeltas] self.remote.get_testrun_states(testrun_ids, self) self._timedeltas = timedeltas def _on_get_event_sequence(self, event_sequence): """ Handler for `get_event_sequence` @type: C{list} of C{str} @param: The sequence of events corresponding to the timedeltas """ if self._steps is None: self._steps = [] for idx in range(1, len(event_sequence)): step = "%s->%s" % (event_sequence[idx - 1], event_sequence[idx]) self._steps.append(step) def _on_get_total_no_of_testruns(self, no_of_runs): """ Handler for `get_total_no_of_testruns` @type: C{int} @param: The total no of runs that have been monitored for the device group selection """ self._no_of_runs = no_of_runs self._end_step = no_of_runs self.remote.get_timedeltas(self._end_step - self.CHUNK_SIZE, self._end_step, -1, DEVICE_GROUP, self) def _on_get_testrun_states(self, states): """ Handler for `get_testrun_states` @type: C{list} of C{str} @param: The states of the queried testruns """ self._testrun_states = states self._render(self._timedeltas) self.update() def onForward(self): """ Forward Click handler """ start = self._end_step - (2 * self.CHUNK_SIZE) start = max(0, start) end = start + self.CHUNK_SIZE self.remote.get_timedeltas(start, end, -1, None, self) self._end_step = end def onBack(self): """ Back Click handler """ end = self._end_step + (2 * self.CHUNK_SIZE) end = min(end, self._no_of_runs) start = end - self.CHUNK_SIZE self.remote.get_timedeltas(start, end, -1, None, self) self._end_step = end
class GChartExample02(GChart): def __init__(self): GChart.__init__(self) self.updateButton = Button( "<b><big>Generate New Simulated Revenues</big></b>") self.setChartSize(WIDTH, HEIGHT) self.setChartTitle("<b><big><big>" + "Simulated Quarterly Revenues" + "</big></big><br> </b>") self.updateButton.addClickListener(self) self.setChartFootnotes(self.updateButton) for iCurve in range(len(barLabels)): self.addCurve() # one curve per quarter self.getCurve().getSymbol().setSymbolType( SymbolType.VBAR_SOUTHWEST) self.getCurve().getSymbol().setBackgroundColor(barColors[iCurve]) self.getCurve().setLegendLabel(barLabels[iCurve]) self.getCurve().getSymbol().setHovertextTemplate( formatAsHovertext(barLabels[iCurve] + " revenue=${y}")) self.getCurve().getSymbol().setModelWidth(1.0) self.getCurve().getSymbol().setBorderColor("black") self.getCurve().getSymbol().setBorderWidth(1) for jGroup in range(len(groupLabels)): # the '+1' creates a bar-sized gap between groups y = rnd() * MAX_REVENUE print "x, y", 1 + iCurve + jGroup * (len(barLabels) + 1), y self.getCurve().addPoint( 1 + iCurve + jGroup * (len(barLabels) + 1), y) self.getCurve().getPoint().setAnnotationText(barLabels[iCurve]) self.getCurve().getPoint().setAnnotationLocation( AnnotationLocation.NORTH) for i in range(len(groupLabels)): # formula centers tick-label horizontally on each group self.getXAxis().addTick( len(barLabels) / 2. + i * (len(barLabels) + 1), groupLabels[i]) self.getXAxis().setTickLabelFontSize(20.0) self.getXAxis().setTickLabelThickness(40.0) self.getXAxis().setTickLength(6.0) # small tick-like gap... self.getXAxis().setTickThickness(0) # but with invisible ticks self.getXAxis().setAxisMin(0) # keeps first bar on chart self.getYAxis().setAxisMin(0) # Based on sim revenue range self.getYAxis().setAxisMax(MAX_REVENUE) # of 0 to MAX_REVENUE. self.getYAxis().setTickCount(11) self.getYAxis().setHasGridlines(True) self.getYAxis().setTickLabelFormat("$#,###") def onClick(self, event): for iCurve in range(self.getNCurves()): for iPoint in range(self.getCurve(iCurve).getNPoints()): self.getCurve(iCurve).getPoint(iPoint).setY(rnd() * MAX_REVENUE) self.update()
class LargeQueryTab(TickeryTab): # Define these in subclasses instructions = None instructionsTitle = None tabName = None defaultQuery = None def __init__(self, topPanel): TickeryTab.__init__(self, topPanel) # Get the query string and wanted tab, if any, from URL args. args = Window.getLocation().getSearchDict() query = args.get('query') wantedTab = args.get('tab') if wantedTab: wantedTab = wantedTab.lower() if query and wantedTab == self.tabName.lower(): query = urllib.unquote_plus(query) self.autoActivate = True else: query = self.defaultQuery self.instructions.setHorizontalAlignment(HasAlignment.ALIGN_LEFT) self.instructions.setStyleName('instructions-popup') self.popup = InstructionBox( self.__class__.__name__, self.instructions) self.popup.setText(self.instructionsTitle) self.db = Button(HELP_TEXT, StyleName='help-button') self.db.addClickListener(self) huhId = HTMLPanel.createUniqueId() help = HTMLPanel('%s <span id="%s"></span>' % (SHORT_INSTRUCTIONS[self.tabName], huhId), StyleName='simple-instructions') help.add(self.db, huhId) self.goButton = go.GoButton(self) self.query = text.TextAreaFocusHighlight(Text=query, VisibleLines=3, StyleName='large-query-area') self.checkResult = HorizontalPanel(Spacing=4) mainGrid = Grid(2, 2, StyleName='tickery-tab-panel', HorizontalAlignment=HasAlignment.ALIGN_LEFT) formatter = mainGrid.getCellFormatter() mainGrid.setWidget(0, 0, help) mainGrid.setWidget(1, 0, self.query) mainGrid.setWidget(1, 1, self.goButton) formatter.setHorizontalAlignment(0, 0, 'left') formatter.setHorizontalAlignment(1, 0, 'left') formatter.setAlignment(1, 1, 'left', 'bottom') self.topGrid.setWidget(0, 1, mainGrid) self.add(self.checkResult) self.results = userlist.UserListPanel(self, topPanel, HorizontalAlignment=HasAlignment.ALIGN_LEFT) self.add(self.results) def setInputFocus(self): self.query.setFocus(True) def clearResults(self): self.results.clear() def clearCheckResult(self): self.checkResult.clear() def onClick(self, sender): if sender == self.db: width = (Window.getClientWidth() - POPUP_WIDTH) / 2.0 self.popup.setPopupPosition(width, 100) self.popup.show() else: self.process() def process(self): self.clearCheckResult() self.clearResults() text = self.query.getText() query = text.strip() if query: self.query.setCursorPos(len(text)) self.goButton.setEnabled(False) checkWidget = results.ResultHandler( query, self, self.tabName, titleMaker) remote = server.TickeryService() f = getattr(remote, self.goButtonRemoteMethod) id = f(self.topPanel.loginPanel.oauthCookie, self.tabName, query, checkWidget) if id < 0: self.checkResult.add(Label('oops!', StyleName='userlist-error-title')) else: self.checkResult.add(Label('Try a non-empty query!', StyleName='userlist-error-title')) def resultsLink(self): d = { 'query' : self.query.getText().strip(), 'sort' : userlist._sortKey, 'icon' : userlist._iconSize, 'tab' : self.tabName, } return '%s?%s' % (defaults.TICKERY_URL, urllib.urlencode(d)) def adjustSize(self, width, height): self.results.adjustSize(width, height)
class GChartExample02(GChart): def __init__(self): GChart.__init__(self) self.updateButton = Button("<b><big>Generate New Simulated Revenues</big></b>") self.setChartSize(WIDTH, HEIGHT) self.setChartTitle("<b><big><big>" + "Simulated Quarterly Revenues" + "</big></big><br> </b>") self.updateButton.addClickListener(self) self.setChartFootnotes(self.updateButton) for iCurve in range(len(barLabels)): self.addCurve() # one curve per quarter self.getCurve().getSymbol().setSymbolType(SymbolType.VBAR_SOUTHWEST) self.getCurve().getSymbol().setBackgroundColor(barColors[iCurve]) self.getCurve().setLegendLabel(barLabels[iCurve]) self.getCurve().getSymbol().setHovertextTemplate( formatAsHovertext(barLabels[iCurve] + " revenue=${y}")) self.getCurve().getSymbol().setModelWidth(1.0) self.getCurve().getSymbol().setBorderColor("black") self.getCurve().getSymbol().setBorderWidth(1) for jGroup in range(len(groupLabels)): # the '+1' creates a bar-sized gap between groups y = rnd()*MAX_REVENUE print "x, y", 1+iCurve+jGroup*(len(barLabels)+1), y self.getCurve().addPoint(1+iCurve+jGroup*(len(barLabels)+1), y) self.getCurve().getPoint().setAnnotationText(barLabels[iCurve]) self.getCurve().getPoint().setAnnotationLocation( AnnotationLocation.NORTH) for i in range(len(groupLabels)): # formula centers tick-label horizontally on each group self.getXAxis().addTick( len(barLabels)/2. + i*(len(barLabels)+1), groupLabels[i]) self.getXAxis().setTickLabelFontSize(20.0) self.getXAxis().setTickLabelThickness(40.0) self.getXAxis().setTickLength(6.0); # small tick-like gap... self.getXAxis().setTickThickness(0); # but with invisible ticks self.getXAxis().setAxisMin(0); # keeps first bar on chart self.getYAxis().setAxisMin(0); # Based on sim revenue range self.getYAxis().setAxisMax(MAX_REVENUE); # of 0 to MAX_REVENUE. self.getYAxis().setTickCount(11) self.getYAxis().setHasGridlines(True) self.getYAxis().setTickLabelFormat("$#,###") def onClick(self, event): for iCurve in range(self.getNCurves()): for iPoint in range(self.getCurve(iCurve).getNPoints()): self.getCurve(iCurve).getPoint(iPoint).setY(rnd()*MAX_REVENUE) self.update()
class SimpleEditor(CustomEditor): """ Simple style of editor for instances, which displays a button. Clicking the button displays a dialog box in which the instance can be edited. """ # Class constants: orientation = "horizontal" extra = 2 # --------------------------------------------------------------------------- # Creates the editor control: # --------------------------------------------------------------------------- def create_editor(self, parent, layout): """ Creates the editor control (a button). """ self._button = Button() layout.add(self._button) self._button.addClickListener(self.edit_instance) # --------------------------------------------------------------------------- # Edit the contents of the object trait when the user clicks the button: # --------------------------------------------------------------------------- def edit_instance(self): """ Edit the contents of the object trait when the user clicks the button. """ # Create the user interface: factory = self.factory view = self.ui.handler.trait_view_for(self.ui.info, factory.view, self.value, self.object_name, self.name) ui = self.value.edit_traits(view, kind=factory.kind, id=factory.id) # Make sure the editor is properly disposed # QtCore.QObject.connect( self._button, QtCore.SIGNAL( 'destroyed()' ), # lambda: ui.dispose() ) # Check to see if the view was 'modal', in which case it will already # have been closed (i.e. is None) by the time we get control back: if ui.control is not None: # Position the window on the display: position_window(ui.control) # Chain our undo history to the new user interface if it does not # have its own: if ui.history is None: ui.history = self.ui.history # --------------------------------------------------------------------------- # Resynchronizes the contents of the editor when the object trait changes # external to the editor: # --------------------------------------------------------------------------- def resynch_editor(self): """ Resynchronizes the contents of the editor when the object trait changes externally to the editor. """ button = self._button if button is not None: label = self.factory.label if label == "": label = user_name_for(self.name) button.setText(label) button.setEnabled(isinstance(self.value, HasTraits))
def addMovie(self, sender, movie): self.movies.append(movie) row = self.moviesFlexTable.getRowCount() self.moviesFlexTable.setText(row, 1, movie.category) self.moviesFlexTable.setText(row, 2, movie.name) self.moviesFlexTable.setText(row, 3, movie.rating) # Adds buttons for remove, edit, save and cancel removeMovieButton = Button("x") editMovieButton = Button("Edit") saveButton = Button("Save") cancelButton = Button("Cancel") # Save and cancel are hidden by default saveButton.setVisible(False) cancelButton.setVisible(False) # Add buttons to row buttons = HorizontalPanel() buttons.add(removeMovieButton) buttons.add(editMovieButton) buttons.add(cancelButton) buttons.add(saveButton) self.moviesFlexTable.setWidget(row, 0, buttons) def removeMovieButton_Click(sender): self.remote.deleteMovie((movie.name, movie.category), self) removeMovieButton.addClickListener(removeMovieButton_Click) def editMovieButton_Click(sender): # Add textboxes and listbox editMovieButton.setVisible(False) cancelButton.setVisible(True) saveButton.setVisible(True) editCategory = TextBox() editName = TextBox() editRating = ListBox(False) for i in range(self.MAX_RATING + 1): editRating.addItem(str(i)) # Variable width textboxes catlen = len(movie.category) namelen = len(movie.name) if (catlen > 8): editCategory.setWidth(str(catlen*10) + "px") else: editCategory.setWidth("80px") if (namelen > 8): editName.setWidth(str(namelen*10) + "px") else: editName.setWidth("80px") self.moviesFlexTable.setWidget(row, 1, editCategory) self.moviesFlexTable.setWidget(row, 2, editName) self.moviesFlexTable.setWidget(row, 3, editRating) editCategory.setText(movie.category) editName.setText(movie.name) editRating.setSelectedIndex(movie.rating) editMovieButton.addClickListener(editMovieButton_Click) def saveButton_Click(sender): catText = self.moviesFlexTable.getWidget(row, 1) nameText = self.moviesFlexTable.getWidget(row, 2) ratingList = self.moviesFlexTable.getWidget(row, 3) newCategory = catText.getText().trim().lower() newCategory = newCategory[0].upper() + newCategory[1:] newName = nameText.getText().trim() newRating = ratingList.getSelectedIndex() if not self.verifyInputs(newName, newCategory): return # Removes temporarily to check for duplicates self.movies.remove(movie) newMovie = Movie(newName, newCategory, newRating) if newMovie in self.movies: Window.alert("'" + newName + "' is already in table.") nameText.selectAll() return self.remote.editMovie((movie.name, movie.category), (newMovie.name, newMovie.category, newMovie.rating), self) saveButton.addClickListener(saveButton_Click) def cancelButton_Click(sender): self.moviesFlexTable.remove(self.moviesFlexTable.getWidget(row, 1)) self.moviesFlexTable.remove(self.moviesFlexTable.getWidget(row, 2)) self.moviesFlexTable.remove(self.moviesFlexTable.getWidget(row, 3)) # Reverts fields to old movie info self.moviesFlexTable.setText(row, 1, movie.category) self.moviesFlexTable.setText(row, 2, movie.name) self.moviesFlexTable.setText(row, 3, movie.rating) cancelButton.setVisible(False) saveButton.setVisible(False) editMovieButton.setVisible(True) cancelButton.addClickListener(cancelButton_Click)
class MainPanel(VerticalPanel): CANVAS_WIDTH = 900 CANVAS_HEIGHT = 700 def __init__(self, owner): super(VerticalPanel, self).__init__() self.edgequeue = list() self.owner = owner self.InitialiseScreen() StaticObjectsTask(self.Draw).schedule(5000) #Poll every five seconds def EdgeListener(self, edge): self.edgequeue.append(edge.asDict()) EdgePoster(self.edgequeue).schedule(1) #Schedule in the future so edges are sent in bulk def InitialiseScreen(self): hpanel = HorizontalPanel() self.add(hpanel) vpanelMenu = VerticalPanel() hpanel.add(vpanelMenu) self.addbutton = Button("Add Triangle") vpanelMenu.add(self.addbutton) self.addbutton.addClickListener(getattr(self, "addtriangle")) self.canvas = GWTCanvas(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) vpanelCanvas = VerticalPanel() self.canvas.setWidth(self.CANVAS_WIDTH) self.canvas.setHeight(self.CANVAS_HEIGHT) hpanel.add(vpanelCanvas) vpanelCanvas.add(self.canvas) self.canvas.addMouseListener(self) self.selecteditem = None self.selectedhandle = None self.mouseisdown = False dc = DocumentCollection.documentcollection DocumentCollection.documentcollection.edgelistener = self.EdgeListener if len(dc.documentsbyclass[model.Drawing.__name__]) == 0: drawing = model.Drawing(None) dc.AddDocumentObject(drawing) EdgePoster([a.asDict() for a in drawing.history.GetAllEdges()]) else: for k,v in dc.documentsbyclass[model.Drawing.__name__].iteritems(): drawing = v self.drawingid = drawing.id self.Draw() def GetDrawing(self): return DocumentCollection.documentcollection.objectsbyid[self.drawingid] def sortfn(self, t1, t2): return cmp(t1.z_order, t2.z_order) def GetTrianglesAsList(self): #Return the triangles as an ordinary python list #triangles = [self.drawing.triangles.GetDocument().documentobjects[objid] for objid in self.drawing.triangles] triangles = list() for triangle in self.GetDrawing().triangles: #triangles = self.drawing.GetDocument().documentobjects[objid] triangles.append(triangle) if len(triangles) > 0: triangles.sort(self.sortfn) return triangles def DrawHandle(self,x,y): self.canvas.setFillStyle(Color.RED) self.canvas.beginPath() self.canvas.arc(x, y, 5, 0, math.pi * 2, False) self.canvas.fill() def Draw(self): self.canvas.setFillStyle(Color.WHITE) self.canvas.fillRect(0, 0, self.CANVAS_WIDTH, self.CANVAS_HEIGHT) for t in self.GetTrianglesAsList(): self.canvas.setFillStyle(Color.BLUE) self.canvas.setLineWidth(5) self.canvas.setStrokeStyle(Color.BLACK) self.canvas.setLineWidth(2) self.canvas.beginPath() self.canvas.moveTo(t.x1, t.y1) self.canvas.lineTo(t.x2, t.y2) self.canvas.lineTo(t.x3, t.y3) self.canvas.lineTo(t.x1, t.y1) self.canvas.fill() self.canvas.stroke() if self.selecteditem == t: self.canvas.setLineWidth(1) self.canvas.setStrokeStyle(Color.RED) self.canvas.beginPath() self.canvas.moveTo(t.x1, t.y1) self.canvas.lineTo(t.x2, t.y2) self.canvas.lineTo(t.x3, t.y3) self.canvas.lineTo(t.x1, t.y1) self.canvas.stroke() self.DrawHandle(t.x1, t.y1) self.DrawHandle(t.x2, t.y2) self.DrawHandle(t.x3, t.y3) def addtriangle(self, sender): left_margin = 50 triangle_spacing = 150 drawing = self.GetDrawing() c = len(drawing.triangles) posx = left_margin + c % ((self.CANVAS_WIDTH - left_margin) // triangle_spacing) * triangle_spacing posy = c // ((self.CANVAS_WIDTH - left_margin) // triangle_spacing) * triangle_spacing t = model.Triangle(None) drawing.triangles.add(t) t.z_order = c setattr(t, 'x1', posx) setattr(t, 'y1', posy + 50) setattr(t, 'x2', posx + 100) setattr(t, 'y2', posy + 100) setattr(t, 'x3', posx + 50) setattr(t, 'y3', posy + 150) self.Draw() def onMouseDown(self, sender, x, y): self.mouseisdown = True if self.selecteditem is not None: self.selectedhandle = None if HandleSelected(x,y, self.selecteditem.x1, self.selecteditem.y1): self.selectedhandle = 1 elif HandleSelected(x,y, self.selecteditem.x2, self.selecteditem.y2): self.selectedhandle = 2 elif HandleSelected(x,y, self.selecteditem.x3, self.selecteditem.y3): self.selectedhandle = 3 if self.selectedhandle is None: self.selecteditem = self.FindTriangle(x,y) if self.selecteditem is None and self.selectedhandle is None: self.selectedhandle = None if self.selecteditem is not None: self.selecteditem.changessuspended = True self.Draw() self.lastx = x self.lasty = y def onMouseMove(self, sender, x, y): if self.selecteditem is not None and self.mouseisdown: diffx = x - self.lastx diffy = y - self.lasty t = self.selecteditem if self.selectedhandle is None: setattr(t, 'x1', t.x1 + diffx) setattr(t, 'y1', t.y1 + diffy) setattr(t, 'x2', t.x2 + diffx) setattr(t, 'y2', t.y2 + diffy) setattr(t, 'x3', t.x3 + diffx) setattr(t, 'y3', t.y3 + diffy) elif self.selectedhandle == 1: setattr(t, 'x1', t.x1 + diffx) setattr(t, 'y1', t.y1 + diffy) elif self.selectedhandle == 2: setattr(t, 'x2', t.x2 + diffx) setattr(t, 'y2', t.y2 + diffy) elif self.selectedhandle == 3: setattr(t, 'x3', t.x3 + diffx) setattr(t, 'y3', t.y3 + diffy) self.lastx = x self.lasty = y self.Draw() def onMouseUp(self, sender,x, y): if self.mouseisdown and self.selecteditem: t = self.selecteditem self.selecteditem.changessuspended = False setattr(t, 'x1', t.x1) setattr(t, 'y1', t.y1) setattr(t, 'x2', t.x2) setattr(t, 'y2', t.y2) setattr(t, 'x3', t.x3) setattr(t, 'y3', t.y3) self.mouseisdown = False def onMouseEnter(self, sender, x, y): pass def onMouseLeave(self, sender, x, y): pass def FindTriangle(self, x, y): pt = Point(x, y) for t in self.GetTrianglesAsList(): if PointInTriangle(pt, t): return t return None
class RolePanel(AbsolutePanel): user = None selectedRole = None roleList = None roleCombo = None addBtn = None removeBtn = None def __init__(self,parent): AbsolutePanel.__init__(self) self.roleList = ListBox() self.roleList.setWidth('300px') self.roleList.setVisibleItemCount(6) self.roleList.addClickListener(self.onListClick) self.roleList.addKeyboardListener(self) self.roleCombo = ListBox() self.roleCombo.addClickListener(self.onComboClick) self.roleCombo.addKeyboardListener(self) self.addBtn = Button("Add", self) self.addBtn.addClickListener(self.onAdd) self.addBtn.setEnabled(False) self.removeBtn = Button("Remove", self) self.removeBtn.addClickListener(self.onRemove) self.removeBtn.setEnabled(False) vpanel = VerticalPanel() vpanel.add(self.roleList) hpanel = HorizontalPanel() hpanel.add(self.roleCombo) hpanel.add(self.addBtn) hpanel.add(self.removeBtn) vpanel.add(hpanel) self.add(vpanel) return def updateRoleList(self,items): self.roleList.clear() for item in items: self.roleList.addItem(item) #self.roleList.addItem(' ') #self.roleList.addItem('- - - - - - - -') def updateRoleCombo(self,choices, default_): self.roleCombo.clear() for choice in choices: self.roleCombo.addItem(choice) self.roleCombo.selectValue(default_) def onComboClick(self, sender, keyCode=None, modifiers=None): selected = self.roleCombo.getSelectedItemText() if not selected or not self.user: self.addBtn.setEnabled(False) self.selectedRole=None else: self.addBtn.setEnabled(True) self.selectedRole=selected[0] self.removeBtn.setEnabled(False) self.roleList.setItemTextSelection(None) def onListClick(self, sender): selected = self.roleList.getSelectedItemText() if selected: self.removeBtn.setEnabled(True) self.selectedRole=selected[0] else: self.removeBtn.setEnabled(False) self.selectedRole=None self.addBtn.setEnabled(False) self.roleCombo.setItemTextSelection(None) def onAdd(self, evt): self.mediator.sendNotification(EmployeeAdmin.AppFacade.ADD_ROLE,self.selectedRole) def onRemove(self,evt): self.mediator.sendNotification(EmployeeAdmin.AppFacade.REMOVE_ROLE,self.selectedRole) def onClick(self, sender): pass def onKeyUp(self, sender, keyCode, modifiers): if sender == self.roleCombo: self.onComboClick(sender) elif sender == self.roleList: self.onListClick(sender) def onKeyDown(self, sender, keyCode, modifiers): pass def onKeyPress(self, sender, keyCode, modifiers): pass