AppController.py :  » Development » PyObjC » trunk » pyobjc » pyobjc-framework-Quartz » Examples » QuartzComposer » Chart » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » PyObjC 
PyObjC » trunk » pyobjc » pyobjc framework Quartz » Examples » QuartzComposer » Chart » AppController.py
from Cocoa import *
from Quartz import *

# APPLICATION DATA STORAGE NOTES:
# - This application uses a simple data storage as an array of entries, 
#   each containing two attributes: a label and a value
# - The array is represented as a NSMutableArray, the entries as 
#   NSMutableDictionaries, the label as a NSString with the "label" key and 
#   the value as a NSNumber with the "value" key
#
#
# QUARTZ COMPOSER COMPOSITION NOTES:
# - The enclosed Quartz Composer composition renders a 3D bars chart and is 
#   loaded on the QCView in the application's window
# - This composition has three input parameters:
#   * "Data": the data to display by the chart which must be formatted as a 
#     NSArray of NSDictionaries, each NSDictionary containing "label" / NSString
#     and "value" / NSNumber value-key pairs
#   * "Scale": a NSNumber used to scale the chart bars
#   * "Spacing": a NSNumber indicating the extra spacing between the chart bars
# - The "Data" and "Scale" input parameters are set programmatically while the 
#   "Spacing" is set directly from the UI through Cocoa bindings
# - Note that this composition is quite simple and has the following 
#   limitations:
#   * it may have rendering artifacts when looking at the chart from some angles
#   * it does not support negative values
#   * labels are not truncated if too long
# - Basically, the composition performs the following:
#   * renders a background gradient
#   * draws three planes on the X, Y and Z axes
#   * uses an Iterator patch to loop on the chart data, which is available as 
#     a Structure, and for each member, retrieves the label and value, then 
#     draws them
#   * the chart rendering is enclosed into a Camera macro patch used to center 
#     it in the view
#   * the Camera macro patch is itself enclosed into a TrackBall macro patch 
#     so that the user can rotate the chart with the mouse
#   * the TrackBall macro patch is itself enclosed into a Lighting macro patch 
#     so that the chart is lighted
# - This composition makes uses of transparency for a nicer effect, but 
#   neither OpenGL nor Quartz Composer handle automatically proper rendering 
#   of mixed opaque and transparent 3D objects
# - A simple, but not fail-proof, algorithm to render opaque and transparent 
#   3D objects is to: 
#   * render opaque objects first with depth testing set to "Read / Write"
#   * render transparent objects with depth testing set to "Read-Only"
#
#
#  NIB FILES NOTES:
# - The QCView is configured to start rendering automatically and forward user 
#   events (mouse events are required to rotate the chart)
# - An AppController instance is connected as the data source for the 
#   NSTableView
# - The NSTableView is set up so that the identifiers of table columns match 
#   the keys used in the data storage
# - The "Value" column of the NSTableView has a NSNumberFormatter which 
#   guarantees only positive or null numbers can be entered here
# - The "Label" column of the NSTableView simply contains text
#

# Keys for the entries in the data storage 
kDataKey_Label = "label" # NSString
kDataKey_Value = "value" # NSNumber

# Keys for the composition input parameters
kParameterKey_Data      = "Data"    # NSArray of NSDictionaries
kParameterKey_Scale  = "Scale"   # NSNumber
kParameterKey_Spacing  = "Spacing" # NSNumber
  
class AppController (NSObject):
    tableView = objc.IBOutlet()
    view = objc.IBOutlet()
  
    _data = objc.ivar()

    def init(self):
        # Allocate our data storage
        self = super(AppController, self).init()
        if self is None:
            return None

        self._data = []
        
        return self

    def awakeFromNib(self):
        # Load the composition file into the QCView (because this 
        # QCView is bound to a QCPatchController in the nib file, this 
        # will actually update the QCPatchController along with all the 
        # bindings)
        if not self.view.loadCompositionFromFile_(NSBundle.mainBundle().pathForResource_ofType_("Chart", "qtz")):
            NSLog("Composition loading failed")
            NSApp.terminate_(None)
            
        # Populate data storage
        self._data.extend([
            {
                kDataKey_Label:"Palo Alto",
                kDataKey_Value: 2,
            },
            {
                kDataKey_Label: "Cupertino",
                kDataKey_Value: 1,
            },
            {
                kDataKey_Label: "Menlo Park",
                kDataKey_Value: 4,
            },
            {
                kDataKey_Label: "Mountain View",
                kDataKey_Value: 8,
            },
            {
                kDataKey_Label: "San Francisco",
                kDataKey_Value: 7,
            },
            {
                kDataKey_Label: "Los Altos",
                kDataKey_Value: 3,
            },
        ])
        
        #Initialize the views
        self.tableView.reloadData()
        self.updateChart()

    def updateChart(self):
        #Update the data displayed by the chart - it will be converted to a 
        # Structure of Structures by Quartz Composer
        self.view.setValue_forInputKey_(self._data, kParameterKey_Data)
            
        #Compute the maximum value and set the chart scale accordingly
        max = 0.0
        for obj in self._data:
            value = obj[kDataKey_Value]
            if value > max:
                max = value

        if max == 0.0:
            scale = 1.0
        else:
            scale = 1/max
        self.view.setValue_forInputKey_(scale, kParameterKey_Scale)

    @objc.IBAction
    def addEntry_(self, sender):
        #Add a new entry to the data storage
        self._data.append({
            kDataKey_Label: "Untitled",
            kDAtaKey_Value: 0,
        })
            
        #Notify the NSTableView and update the chart
        self.tableView.reloadData()
        self.updateChart()
        
        #Automatically select and edit the new entry
        self.tableView.selectRow_byExtendingSelection(len(self._data)-1, False)
        self.tableView.editColumn_row_withEvent_select_(
                self.tableView.columnWithIdentifier_(kDataKey_Label),
                len(self._data)-1, None, True)

    @objc.IBAction
    def removeEntry_(self, sender):
        #Make sure we have a valid selected row
        selectedRow = self.tableView.selectedRow()
        if selectedRow < 0 or tableView.editedRow() == selectedRow:
            return
            
        #Remove the currently selected entry from the data storage
        del self._data[selectedRow]
            
        #Notify the NSTableView and update the chart
        self.tableView.reloadData()
        self.updateChart()

     
    def numberOfRowsInTableView_(self, aTableView):
        # Return the number of entries in the data storage
        return len(self._data)

    def tableView_objectValueForTableColumn_row_(self, aTableView, aTableColumn, rowIndex):
        # Get the "label" or "value" attribute of the entry from the data 
        # storage at index "rowIndex"
        return self._data[rowIndex][aTableColumn.identifier()]

    def tableView_setObjectValue_forTableColumn_row_(
            self, aTableView, anObject, aTableColumn, rowIndex):

        # Set the "label" or "value" attribute of the entry from the data 
        # storage at index "rowIndex"
        self._data[rowIndex][aTableColumn.identifier()] = anObject

        # Update the chart
        self.updateChart()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.