Tag Archives: Programming

Roadmap For Gonzales 0.02

For version 0.02 I have the following features in mind:

  1. A simple help system, that shows you the most important features in a consistent way
  2. A snippet system like the ones from Textmate and Scribes. Probably I will steal most of the code from Scribes. Mysteelef’s snippet system is just awesome.
  3. Auto – Indentation hast to be build, especially for Python programming. I think IDLE is working quite fine with Python 🙂 The other languages will become a simpler auto-indentation system.
  4. A way to load a file via command line in one instance of the editor.
  5. Right now the status messages in the status bar are only dummies. I will have to find a way of refresh the state of the status bar.
  6. I want some kind of recent files dialog. Simular to the recent files dialog of Emacs. I think wxPython doesn’t provide any facilities for that, so I have to write it by my self.
  7. Intelligent logging of events and properties. That point needs a lot of thought, what do I want to track, maybe the size of the window, etc.
  8. Auto braces. Here again I will borrow a lot from Scribes. The way the braces work in Scribes is just gorgeous.
  9. Better highlighting. Gonzales needs more highlighting files for languages different from Python
  10. Develop ideas for shortcuts – I have to think about the best use of shortcuts. This is a crucial part of the user experience. A lot of nice ideas can be found on http://xahlee.org/emacs/ergonomic_emacs_keybinding.html.

That’s it for version 0.02. It is a awful lot of work 🙂 But I think after version 0.02 is finished Gonzales could be usable for simple programming tasks.

Advertisements

Gonzales 0.01 Is Out

I played around with the idea of programming my own editor.

I finished my first iteration which I call version 0.01. It is of course more a kind of a prototype than a complete editor. But like every iteration/version it includes 10 new features. (Ergo version 0.1 will include 100 features.)

Features

Now lets introduce the features with screen shots and explanation:

1. Basic Design Ideas (Opera, web2.0 style [rtm, gmail])

Gonzales Main Window + File Switcher

Gonzales Main Window + File Switcher

Gonzales got an reduced window without menu and icons to save screen space and lead the user to the use of shortcuts. The file switcher works like the one from Opera. If you use <Ctrl>+<Tab>, Gonzales show you the last used file. Colors will probably change until version 0.1

2. Autosave (no save as…)

Gonzales saves your file every time it looses focus. There is no such thing like “save” or “save as …”. Every time you create a new file you will be asked for a name and you have to stick to it. If you want to change names you have to use a file manager or something similar.

3. Spaces Instead Of Tabs

All Tabs will be converted to spaces at the moment. Like most features it can easily changed in the configuration files.

4. Tab Width 4 Spaces

This one is closely related to feature 3. Tabwidth is set to 4 spaces.

5. Show Dot For Space

Gonzales shows a dot for every space. This is especially useful for programming python. It can be easily changed in the configuration file.

6. Loading Of File Via Command Line

You can load files via command line. I know this is nothing special, but it was an important feature for me. Right now there is no server to open a new file in a running instance of Gonzales. This will be implemented soon.

7. Set The Right Working Directory

A quite complex algorithm determines which is the current working directory of Gonzales. Usually it is the one of the active file.

8. Simple Open Dialog

Simple Open File Dialog

A Simple Open File Dialog

Gonzales has a rather simple open dialog, it will get pimped later, but I needed a solution for opening files for testing purposes. If you enter an absolute path this path will be used. If you enter a relative path it is relative to the current working dir.

9. Gonzales Closes If Last Tab Is Closed.

Some of you might know this feature from a Firefox plugin. If you close the last tab,
you close the whole app.

10. Basic Syntax-Highlighting

Python Syntax-Highlighting

Python Syntax-Highlighting

Gonzales has syntax highlighting for Python implemented. Highlighting for other languages can now be easily added trough configuration files.

Download

If you want to download Gonzales and play around with it:

http://rockiger.googlecode.com/files/gonzales-0.01.tar.gz

The code is GPL3. Tell me what you think.

Sketch Number 2

Sketch # 2 show an entry field at the bottom. This entry field shall be used for most user entries. This idea is of course stolen from Emacs. The idea is that you can run a lot of commands from there, even if you don’t know the shortcut for the command.

Programming Editor Sketch 2

Sketch 2 - See the entry field at the bottom

I probably will use the classic “Alt-x” or better “M-x” shortcut for the entry field. This is meant as a homage to Emacs.

This little field seams not very significant, but I think it helps a lot to

  • give the user a lot of power and
  • streamlining the editing experience

at the same time.

A New Text Editing Experience

I am unsatisfied of the state of programming editors. At the moment there is no editor that suits all my needs. Don’t get me wrong there are several great text editors out there:

  • Emacs – The most powerful text editing system ever created
  • Scribes – A simply and nevertheless powerful.
  • Peppy – A simpler Emacs in Python

but no one works perfect for me.
Emacs for example has different short cuts than most other software (Yeah, I know you can change that), Schribes only works on Linux, etc.

Designing A New Experience

After searching and experimenting for the perfect editor, I was thinking: “Why not writing a new one?”. After all there is a lot to learn. At first I was thinking about the widget toolkit and features. Then is struck me. Designing from scratch means thinking beyond technical details.

I want a new editing experience:

  1. I want to learn from web apps like Remember The Milk and GMail
  2. I want to streamline the experience, there should be nothing that gets in your way
  3. The interface should be gorgeous. I think that is not emphasized enough in most editors.
  4. The editor should speed you up. Think snippets, call tips, auto completion, etc.
  5. The editor shall be lean.

Then I started experimenting with code…

Pyjamas Tutorial Part 3

This tutorial series is based on the Getting Started tutorial for GWT.

Part 2: Building the User Interface

At this point, you’ve created all the elements of the interface. Like many user interface frameworks, Pyjamas is event-based. This means that the code executes in response to some event occurring. Most often, that event is triggered by the user, who uses the mouse or keyboard to interact with the application interface.

In this section, you’ll wire up your widgets to listen for and handle mouse and keyboard events.

  1. Review the functional requirements.
  2. Listen for events.
  3. Respond to events.
  4. Test event handling.

1. Reviewing the requirements for event handling

Let’s review the StockWatcher requirements to see what events occur.

Task UI Event (Trigger mechanism) Response
User enters a stock code. Clicks the Add button
or presses return in the input box.
  • Verify input.
  • Check to see if stock already exists.
  • Add a new row.
  • Create a delete button.
User deletes stock from the table. Presses the Remove button.
  • Remove row from table.

provides a number of different event handler interfaces. To handle click events on the Add and Remove buttons, you’ll use the build in ClickHandler class of the Button. To handle keyboard events in the input box, you’ll use the KeyPressHandler class.

2. Listening for events

Event Handler Classes

Events in Pyjamas use the event handler model similar to other user interface frameworks. To subscribe to an event, you pass a particular event handler interface to the appropriate widget. An event handler class defines one or more methods that the widget then calls to announce (publish) an event.

Handling Mouse Events

One way StockWatcher users can enter a stock code is by using their mouse to click on the Add button.

You’ll handle the Add button’s click event by just assigning a function to the button, which fires when the user clicks on the widget.

When the user clicks on the Add button, StockWatcher should respond by adding the stock to the stock table. So, to handle the click event, call the addStock method. You haven’t written the addStock method yet; you’ll create a stub and then code it in the next section.

  1. Add a function handler to the Add button so it can receive click events.
    In stockwatcher.py, in the onModuleLoad method, cut and paste the code commented “Listen for mouse events on the Add button.” that is highlighted below.
  2. In stockwatcher.py, create the stub for the addStock method.
    Just copy and paste from the code highlighted below.
    from pyjamas.ui.RootPanel import RootPanel
    from pyjamas.ui.VerticalPanel import VerticalPanel
    from pyjamas.ui.FlexTable import FlexTable
    from pyjamas.ui.HorizontalPanel import HorizontalPanel
    from pyjamas.ui.TextBox import TextBox
    from pyjamas.ui.Button import Button
    from pyjamas.ui.Label import Label
    from pyjamas import Window
    
    class Stockwatcher:
    
        # Entry point method.
        def __init__(self):
    #        declare interface widgets
            self.mainPanel = VerticalPanel()
            self.stocksFlexTable = FlexTable()
            self.addPanel = HorizontalPanel()
            self.newSymbolTextBox = TextBox()
            self.addStockButton = Button("Add", getattr(self, "addStock"))
            self.lastUpdatedLabel = Label()
    
        def addStock(self):
    # Add stock to FlexTable. Executed when the user clicks the
    # addStockButton or presses enter in the newSymbolTextBox.
    
        def onModuleLoad(self):
            # Create table for stock data.
            self.stocksFlexTable.setText(0, 0, "Symbol")
            self.stocksFlexTable.setText(0, 1, "Price")
            self.stocksFlexTable.setText(0, 2, "Change")
            self.stocksFlexTable.setText(0, 3, "Remove")
    
            # Assemble Add Stock panel.
            self.addPanel.add(self.newSymbolTextBox)
            self.addPanel.add(self.addStockButton)
    
            #Assemble Main panel.
            self.mainPanel.add(self.stocksFlexTable)
    
            self.mainPanel.add(self.addPanel)
            self.mainPanel.add(self.lastUpdatedLabel)
    
            #Associate the Main panel with the HTML host page.
            RootPanel().add(self.mainPanel)
    
            # Move cursor focus to the input box.
            self.newSymbolTextBox.setFocus(True)
    
    if __name__ == '__main__':
        app = Stockwatcher()
        app.onModuleLoad()

Handling Keyboard Events

In addition to using the Add button, StockWatcher users can enter a stock code without taking their hands from the keyboard by pressing return in the input box.

To subscribe to keyboard events, you can call the addKeyPressHandler(KeyPressHandler) method and pass it a KeyPressHandler.

    Hook up the keypress event handler for the input box, newSymbolTextBox.
    In the Stockwatcher class, cut and paste the code that is highlighted below.
    
        def onKeyDown(self, sender, keycode, modifiers):
            pass
    
        def onKeyUp(self, sender, keycode, modifiers):
            pass
    
        def onKeyPress(self, sender, keycode, modifiers):
            if sender == self.newSymbolTextBox and \
               keycode == KeyboardListener.KEY_ENTER:
                self.addStock()

The event handlers are now wired up and ready for an event. Your next step is to fill out the stub addStock method.

3. Responding to user events

At this point, StockWatcher should be listening for user input, a mouse or keyboard event that signals the user has entered a stock code. So next you’ll test whether or not the event handler interfaces are working by coding the response that StockWatcher should make when it detects an event: add the stock. StockWatcher responds on the client side without sending any requests back to server or reloading the HTML page.

Adding the stock to the stock table

In StockWatcher, users will enter the stock codes of the stocks they want to monitor one at a time into the input box. When they press Enter or click on the Add button, you want StockWatcher to respond as follows:

  1. Validate the input.
  2. Check for duplicates.
  3. Add the stock.
  4. Add a button for removing the stock from the list.

In this section, you’ll code the first response, validating the input, just to see if the event handler interfaces are working. In the next section, Coding Functionality on the Client, you’ll code the rest of the steps to add the stock.

You’ll implement this functionality in the addStock method.

Validating input in a text box

You want verify that the stock code entered is valid. Rather than verify whether the user input matches an actual stock code, for the purposes of this tutorial, you’ll just perform a simple character validity check.

First, extract the stock code. To retrieve the text in the TextBox widget use its getText method.

Next, ensure that the charcters are not within the set of illegal characters you specify. After you’ve converted the user input to a standard form, use a regular expression to check its format. Remember to use regular expressions.

If the input is valid, clear the text box so the user can add another stock code.

Finally, if the input is not valid, warn users via a dialog box.

  1. Validate user input of the stock code.
    In StockWatcher.java. replace the stub addStock method with following code.
    def addStock(self):
    
    # Add stock to FlexTable. Executed when the user clicks the
    # addStockButton or presses enter in the newSymbolTextBox.
            symbol = self.newSymbolTextBox.getText()
            self.newSymbolTextBox.setText("")
            self.newSymbolTextBox.setFocus(True)
    
            symbol = symbol.upper().strip()
    
            if not testRegEx(symbol):
                Window.alert("Please choose a different name than %s.\n\
                                    The Name should only contain number \
                                     and characters" % (symbol))
                return
    
        # TODO Don't add the stock if it's already in the table.
    
        # TODO Add the stock to the table.
    
        # TODO Add a button to remove this stock from the table.
    
        # TODO Get the stock price.
    
      }
  2. Test the regular expression in Javascript.
    I didn’t figured out how to test regular expression with pyjamas yet. So you have to define this function in your stockwatcher.py
    def testRegEx(string):
        """Test a regular expression"""
        JS("""
            var re = new RegExp("^[0-9a-zA-Z\s]{1,30}$");
    
            return re.test(string);
        """)
    

4. Testing event handling

At this point you should be able to enter text in the input box. If you use an illegal character, a dialog box should pop up and display a warning. Try it and see.

  1. Test event handling in hosted mode.
  2. Test that both event handler interfaces work.
    Enter stock codes in the input box. Enter using both methods, by pressing return and by using the mouse to click on the Add button.
    At this point, the stock is not added to the table. However, the input box should clear so that you can add another stock.
  3. Test the validity checking and error message.
    Make some typos that include illegal characters.

Validation Error Message

What’s Next

At this point you’ve implemented event handler interfaces for mouse and keyboard events that signal the user has entered a stock. Stockwatcher responds by validating the input.

From now on, you should be able to go on your own.

You could improve the client that it adds the stock to the table and provide a button to remove it. See the original Google tutorial for inspiration.

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.

Pyjamas Tutorial Part 2

This tutorial series is based on the Getting Started tutorial for  GWT.

Part1: Designing the Application

At this point, you’ve created the components of the StockWatcher project and reviewed its functional requirements and UI design. In this section, you’ll build the user interface out of Pyjamas widgets and panels.

  1. Select the Pyjamas widgets needed to implement the UI elements.
  2. Select the Pyjamas panels needed to layout the UI elements.
  3. Implement the widgets and panels in StockWatcher.py.
  4. Test the layout.

Pyjamas shields you from worrying too much about cross-browser incompatibilities. If you clonstructonstruct the interface with Pyjamas widgets and composites, your application will work similarly on the most recent versions of Firefox, Internet Explorer, Opera, and Safari. However, DHTML user interfaces remain remarkably quirky; therefore, you still must test your applications thoroughly on every browser.

1. Selecting Pyjamas widgets to implement the UI elements

First, look at the Widget Gallery and select the Pyjamas widget for each UI element. The class names of Pyjamas and Pyjamas are the same in most cases.

In the Widget Gallery the widgets have a default style and so they don’t look exactly as they will in the final implementation of StockWatcher. Don’t worry about that now. First you’ll focus on getting the widgets working. Then, in Applying Styles, you’ll change their appearance with CSS.

Stock Data Table

Pyjamas provides a special table widget called a FlexTable. The FlexTable widget creates cells on demand. This is just what you need for the table containing the stock data because you don’t know how many stocks the user will add. A table implemented with the FlexTable widget will expand or collapse as the user adds or removes stocks.

Buttons

Whenever possible, Pyjamas defers to browsers’ native user interface elements. For instance, a Button widget becomes a true HTML <button> rather than a synthetic button-like widget that’s built, for example, from a <div>. This means that Pyjamas buttons render appropriately in different browsers and on different client operating systems. The benefit of using native browser controls is that they are fast, accessible, and most familiar to users. Also, they can be styled with CSS.

Input Box

Pyjamas provides several widgets to create fields that users can type in:

  • TextBox widget, a single-line text box
  • PassWordTextBox widget, a text box that visually masks input
  • TextArea widget, a multi-line text box
  • SuggestBox, displays a pre-configured set of items

StockWatcher users will type in a stock code which is single line of text; therefore, implement a TextBox widget.

Label

In contrast with the Button widget, the Label widget does not map to the HTML <label> element, used in HTML forms. Instead it maps to a <div> element which contains arbitrary text, not interpreted as HTML. As a <div> element, it is a block-level element rather than an inline element.

<div class="gwt-Label">Last update : Oct 1, 2008 1:31:48 PM</div>

If you’re interested in taking a peek at the API reference for the Pyjamas widgets you’ll use to build the StockWatcher interface, click on the links in the table below.

UI element Pyjamas implementation
a table: to hold the stock data FlexTable widget
two buttons: one to add stocks and one to remove them Button widget
an input box: to enter the stock code TextBox widget
a timestamp: to show the time and date of the last refresh Label widget
a logo image file referenced from HTML host page
a header static HTML in HTML host page
indicate whether the change in price was positive or negative using colors dynamic CSS

In Depth: If you don’t find a widget that meets the functional requirements of your application, you can create your own. For details on creating composite widgets or widgets from scratch using Java or JavaScript, see the Developer’s Guide, Creating Custom Widgets.

2. Selecting panels to layout the UI elements

Now that you know what widgets you’ll use, you’ll decide how to lay them out using Pyjamas panels. Pyjamas provides several types of panels to manage the layout. Panels can be nested within other panels. This is analogous to laying out your web page in HTML using nested div elements or tables. For StockWatcher, you’ll use a Horizontal panel nested within a Vertical panel.

Horizontal Panel

The two elements used to add a stock—the input box for typing in a new stock symbol and the Add button—are closely related functionally and you want keep them together visually. To lay them out side-by-side, you’ll put the TextBox widget and a Button widget in a horizontal panel. In the Java code, you’ll create a new instance of HorizontalPanel and name it addPanel.

Vertical Panel

You want to lay out the remaining elements vertically.

  • the FlexTable widget: the stock table
  • the Add Stock panel: contains the input box and Add button
  • the Label widget: the timestamp

You’ll do this with a vertical panel. In the Java code, you’ll create a new instance of VerticalPanel and name it mainPanel.

Root Panel

There is one more panel you need which is not visible in the user interface: a Root panel. A Root panel is the container for the dynamics elements of your application. It is at the top of any Pyjamas user interface hierarchy. There are two ways you can use a Root panel, either to generate the entire body of the page or to generate specific elements embedded in the body.

The Root panel works by wrapping an element in the HTML host page. By default (that is, if you don’t add any placeholders in the host page) the Root panel wraps the body element. However, you can wrap any element if you name it and then, when you call the Root panel, pass the the name as a parameter. You’ll how this works in the next two sections when you do it for StockWatcher.

RootPanel('').add(self.somethin)             # Default. Wraps the HTML
                                            # body element.

RootPanel('stocklist').add(self.something)  # Wraps any HTML 
                                            # element with an id 
                                            # of "stockList"

A host page can contain multiple Root panels. For example, if you’re embedding multiple widgets or panels into a host page, each one can be implemented independently of the others, wrapped in its own Root panel.

4. Implementing widgets and panels

Next you will construct the user interface from Pyjamas widgets and panels.

Most of the UI is displayed as soon as StockWatcher starts up. So you’ll implement them in the onModuleLoad method. In this section, you will:

  1. Instantiate each widget and panel.
  2. Create the table that holds the stock data.
  3. Lay out the widgets using the Add Stock panel and the Main panel.
  4. Associate the Main panel with the Root panel.
  5. Move the cursor focus to the input box.

You can follow this section of the tutorial step-by-step, or you can cut and paste the entire block of code from the Summary at the end.

1. Instantiate each widget and panel

Instantiate each widget and panel using class field initializers.
Create a Stockwatcher.py file und fill it with the following code
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label

class Stockwatcher:

    # Entry point method.
    def __init__(self):
        #declare interface widgets
        self.mainPanel = VerticalPanel()
        self.stocksFlexTable = FlexTable()
        self.addPanel = HorizontalPanel()
        self.newSymbolTextBox = TextBox()
        self.addStockButton = Button("Add")
        self.lastUpdatedLabel = Label()

    # TODO Create table for stock data.

    # TODO Assemble Add Stock panel.

    # TODO Assemble Main panel.

    # TODO Associate the Main panel with the HTML host page.

    # TODO Move cursor focus to the input box.

if __name__ == '__main__':

    app = Stockwatcher()

    app.onModuleLoad()

2. Create a table for stock data

Implement the table that will hold the stock data. Set up the header row that displays when the user launches StockWatcher. To do this, use the setText method to create labels in the heading of each column: Symbol, Price, Change, Remove.

  1. Create table for stock data.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    from pyjamas.ui.RootPanel import RootPanel
    from pyjamas.ui.VerticalPanel import VerticalPanel
    from pyjamas.ui.FlexTable import FlexTable
    from pyjamas.ui.HorizontalPanel import HorizontalPanel
    from pyjamas.ui.TextBox import TextBox
    from pyjamas.ui.Button import Button
    from pyjamas.ui.Label import Label
    
    class Stockwatcher:
    
        # Entry point method.
        def __init__(self):
            #declare interface widgets
            self.mainPanel = VerticalPanel()
            self.stocksFlexTable = FlexTable()
            self.addPanel = HorizontalPanel()
            self.newSymbolTextBox = TextBox()
            self.addStockButton = Button("Add")
            self.lastUpdatedLabel = Label()
    
        def onModuleLoad(self):
            # Create table for stock data.
            self.stocksFlexTable.setText(0, 0, "Symbol")
            self.stocksFlexTable.setText(0, 1, "Price")
            self.stocksFlexTable.setText(0, 2, "Change")
            self.stocksFlexTable.setText(0, 3, "Remove")
    
        # TODO Assemble Add Stock panel.
    
        # TODO Assemble Main panel.
    
        # TODO Associate the Main panel with the HTML host page.
    
        # TODO Move cursor focus to the input box.
    
    if __name__ == '__main__':
    
        app = Stockwatcher()
    
        app.onModuleLoad()

3. Lay out the widgets

To lay out the widgets, you’ll assemble two panels, the Add Stock panel and the Main panel. First assemble the the Add Stock panel, a horizontal panel which wraps the input box and the Add button. Then assemble the Main panel, a vertical panel that specifies the layout of the stock list table, the Add Stock panel, and the timestamp.

  1. Lay out the widgets in the Add Stock panel and the Main panel.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    from pyjamas.ui.RootPanel import RootPanel
    from pyjamas.ui.VerticalPanel import VerticalPanel
    from pyjamas.ui.FlexTable import FlexTable
    from pyjamas.ui.HorizontalPanel import HorizontalPanel
    from pyjamas.ui.TextBox import TextBox
    from pyjamas.ui.Button import Button
    from pyjamas.ui.Label import Label
    
    class Stockwatcher:
    
        # Entry point method.
        def __init__(self):
            #declare interface widgets
            self.mainPanel = VerticalPanel()
            self.stocksFlexTable = FlexTable()
            self.addPanel = HorizontalPanel()
            self.newSymbolTextBox = TextBox()
            self.addStockButton = Button("Add")
            self.lastUpdatedLabel = Label()
    
        def onModuleLoad(self):
            # Create table for stock data.
            self.stocksFlexTable.setText(0, 0, "Symbol")
            self.stocksFlexTable.setText(0, 1, "Price")
            self.stocksFlexTable.setText(0, 2, "Change")
            self.stocksFlexTable.setText(0, 3, "Remove")
    
            # Assemble Add Stock panel.
            self.addPanel.add(self.newSymbolTextBox)
            self.addPanel.add(self.addStockButton)
    
            #Assemble Main panel.
            self.mainPanel.add(self.stocksFlexTable)
    
            self.mainPanel.add(self.addPanel)
            self.mainPanel.add(self.lastUpdatedLabel)
    
            # TODO Associate the Main panel with the HTML host page.
    
            # TODO Move cursor focus to the input box.
    
    if __name__ == '__main__':
    
        app = Stockwatcher()
    
        app.onModuleLoad()

4. Associate the Main panel with the Root panel

In order for any Pyjamas widget or panel to be embedded in the HTML host page, it must be contained within a Root panel. Associate the Root panel with Vertical panel, mainPanel. The Root panel wraps the HTML element in StockWatcher’s host page that has an id of “stocklist”. In this case, it is a <div> element.

  1. Associate the Main panel with the host page via the Root panel.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    from pyjamas.ui.RootPanel import RootPanel
    from pyjamas.ui.VerticalPanel import VerticalPanel
    from pyjamas.ui.FlexTable import FlexTable
    from pyjamas.ui.HorizontalPanel import HorizontalPanel
    from pyjamas.ui.TextBox import TextBox
    from pyjamas.ui.Button import Button
    from pyjamas.ui.Label import Label
    
    class Stockwatcher:
    
        # Entry point method.
        def __init__(self):
            #declare interface widgets
            self.mainPanel = VerticalPanel()
            self.stocksFlexTable = FlexTable()
            self.addPanel = HorizontalPanel()
            self.newSymbolTextBox = TextBox()
            self.addStockButton = Button("Add")
            self.lastUpdatedLabel = Label()
    
        def onModuleLoad(self):
            # Create table for stock data.
            self.stocksFlexTable.setText(0, 0, "Symbol")
            self.stocksFlexTable.setText(0, 1, "Price")
            self.stocksFlexTable.setText(0, 2, "Change")
            self.stocksFlexTable.setText(0, 3, "Remove")
    
            # Assemble Add Stock panel.
            self.addPanel.add(self.newSymbolTextBox)
            self.addPanel.add(self.addStockButton)
    
            #Assemble Main panel.
            self.mainPanel.add(self.stocksFlexTable)
    
            self.mainPanel.add(self.addPanel)
            self.mainPanel.add(self.lastUpdatedLabel)
    
            #Associate the Main panel with the HTML host page.
            RootPanel().add(self.mainPanel)
    
            # TODO Move cursor focus to the input box.
    
    if __name__ == '__main__':
        app = Stockwatcher()
        app.onModuleLoad()

5. Move cursor focus to the input box

Finally, move the cursor focus to the input box so, when StockWatcher loads, the user can begin adding stocks.

  1. In the onModuleLoad method, replace the TODO comment with the highlighted code.
    from pyjamas.ui.RootPanel import RootPanel
    from pyjamas.ui.VerticalPanel import VerticalPanel
    from pyjamas.ui.FlexTable import FlexTable
    from pyjamas.ui.HorizontalPanel import HorizontalPanel
    from pyjamas.ui.TextBox import TextBox
    from pyjamas.ui.Button import Button
    from pyjamas.ui.Label import Label
    
    class Stockwatcher:
    
        # Entry point method.
        def __init__(self):
            #declare interface widgets
            self.mainPanel = VerticalPanel()
            self.stocksFlexTable = FlexTable()
            self.addPanel = HorizontalPanel()
            self.newSymbolTextBox = TextBox()
            self.addStockButton = Button("Add")
            self.lastUpdatedLabel = Label()
    
        def onModuleLoad(self):
            # Create table for stock data.
            self.stocksFlexTable.setText(0, 0, "Symbol")
            self.stocksFlexTable.setText(0, 1, "Price")
            self.stocksFlexTable.setText(0, 2, "Change")
            self.stocksFlexTable.setText(0, 3, "Remove")
    
            # Assemble Add Stock panel.
            self.addPanel.add(self.newSymbolTextBox)
            self.addPanel.add(self.addStockButton)
    
            #Assemble Main panel.
            self.mainPanel.add(self.stocksFlexTable)
    
            self.mainPanel.add(self.addPanel)
            self.mainPanel.add(self.lastUpdatedLabel)
    
            #Associate the Main panel with the HTML host page.
            RootPanel().add(self.mainPanel)
    
            # Move cursor focus to the input box.
            self.newSymbolTextBox.setFocus(True)
    
    if __name__ == '__main__':
        app = Stockwatcher()
        app.onModuleLoad()

Summary

Here’s what you’ve done to this point.

from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label

class Stockwatcher:

    # Entry point method.
    def __init__(self):
        #declare interface widgets
        self.mainPanel = VerticalPanel()
        self.stocksFlexTable = FlexTable()
        self.addPanel = HorizontalPanel()
        self.newSymbolTextBox = TextBox()
        self.addStockButton = Button("Add")
        self.lastUpdatedLabel = Label()

    def onModuleLoad(self):
        # Create table for stock data.
        self.stocksFlexTable.setText(0, 0, "Symbol")
        self.stocksFlexTable.setText(0, 1, "Price")
        self.stocksFlexTable.setText(0, 2, "Change")
        self.stocksFlexTable.setText(0, 3, "Remove")

        # Assemble Add Stock panel.
        self.addPanel.add(self.newSymbolTextBox)
        self.addPanel.add(self.addStockButton)

        #Assemble Main panel.
        self.mainPanel.add(self.stocksFlexTable)

        self.mainPanel.add(self.addPanel)
        self.mainPanel.add(self.lastUpdatedLabel)

        #Associate the Main panel with the HTML host page.
        RootPanel().add(self.mainPanel)

        # Move cursor focus to the input box.
        self.newSymbolTextBox.setFocus(True)

if __name__ == '__main__':
    app = Stockwatcher()
    app.onModuleLoad()

5. Testing the layout

  1. Save the edited files.
    Save StockWatcher.py
  2. Compile the edited files.
    Compile your StockWatcher.py in debugging mode path/to/pyjamas/bin/pyjsbuild .py StockWatcher.py -d
  3. Launch StockWatcher in in your browser.
    Open output/StockWatcher.htmlfrom your StockWatcher directory in your browser.
  4. You should see your first iteration of StockWatcher
    StockWatcher displays the header of the flex table, the input box and the Add button. You haven’t set the text for the Label, yet; so, it isn’t displayed. You’ll do that after you’ve implemented the stock refresh mechanism.
  5. Leave StockWatcher running in hosted mode.
    In the rest of this tutorial, you’ll frequently be testing changes in hosted mode.

Refreshing Hosted Mode

Best Practices: You should compile your app and reload your browser very often. Don’t do to many steps at once.

What’s Next

At this point you’ve built the basic UI components of StockWatcher by implementing Pyjamas widgets and panels. The widgets don’t respond to any input yet.

Now you’re ready to code event handling on the client. You’ll wire up the widgets to listen for events and write the code that responds to those events.

Step 3: Managing Events on the Client

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.

Pyjamas Tutorial Part 1

I will post a tutorial series about Pyjamas the superb Python to Javascript compiler. This tutorial series will be based on the Getting Started tutorial for GWT. I will assume that you have Pyjamas correctly installed on your plattform (Linux, Mac, Win).

In this section, you’ll review the functional requirements and design the user interface.

  1. Examine the functional requirements.
  2. Identify the elements of the UI design.

1. Examining the functional requirements

Initially you want the StockWatcher application to do six things.

Stockwatcher Application Scribble
Stockwatcher Application Scribble
  • Provide users with the ability to add stocks. (Supply simple validation on input for illegal characters or existing stock.)
  • Display the following information for each stock: symbol, price, change since last refresh.
  • Provide users with the ability to delete a stock from the list.

2. Identifying the elements of the UI design

After studying StockWatcher’s functional requirements, you decide you need these UI elements.

  • a table: to hold the stock data
  • two buttons: one to add stocks and one to remove them
  • an input box: to enter the stock code
  • a timestamp: to show the time and date of the last refresh
  • a logo
  • a header
  • indicate whether the change in price was positive or negative using colors

Including Static Elements

Pyjamas does not dictate how you lay out your HTML page. A GWT application can take up the entire browser window, as it does in the startup application. Or it can be embedded in an existing page, as it is in the Getting Started page of this tutorial.

The StockWatcher application contains both static and dynamic elements. The logo and the header “StockWatcher” are static elements in the HTML host page. All the other elements are created programmatically using Pyjamas.

What’s Next

At this point you’ve reviewed StockWatcher’s functional requirements. You have a clear idea of what StockWatcher does. You know what UI elements you need to implement and how you want to lay them out.

Now you’re ready to build the user interface using GWT widgets and panels.

Coming soon:
Part 2: Building the User Interface

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.