SlideShare uma empresa Scribd logo
1 de 68
Brew up a Rich
Web Application
with Cappuccino
Howard M. Lewis Ship
TWD Consulting
hlship@comcast.net
                       1   © 2009 Howard Lewis Ship
Three 'C's,
 Two 'P's,
  One 'N'
     2   © 2009 Howard Lewis Ship
Agenda
• Why Cappuccino?
• Getting Started
• Objective-J
• Running as a Web App
• Window Resizing &
  Remote Communication
• Cappuccino Pitfalls




                         3   © 2009 Howard Lewis Ship
Why Cappuccino?

          4       © 2009 Howard Lewis Ship
5   © 2009 Howard Lewis Ship
6   © 2009 Howard Lewis Ship
❝If you need web applications that offer
the same user experience as a desktop
app would, then Cappuccino is for you. If
you truly believe that the classic web
development "components" - the usual
HTML/CSS/Javascript horror shop -
simply stinks, then you are going to be
delighted about Cappuccino, too.❞


Holger Jahn
                    7               © 2009 Howard Lewis Ship
Getting Started

            8     © 2009 Howard Lewis Ship
Download
   http://cappuccino.org/download/




                                     Click Here




                    9                  © 2009 Howard Lewis Ship
Install Tools
                     sudo ./install-tools




                10                    © 2009 Howard Lewis Ship
Tools Install
• Pre-Requisites

  • Mac or Linux Helps!

  • Cygwin for Windows

  • Ruby & Rake

•cd Tools ; sudo ./install-tools

• Tools & Frameworks installed to   /usr/local/share


• Must add /usr/local/share/bin to $PATH

                              11                       © 2009 Howard Lewis Ship
Create Example
                capp gen example




           12                  © 2009 Howard Lewis Ship
Generated Files

Info.plist         Application startup information

main.j             main() method for application

AppController.j    Application controller (builds initial UI)

index.html         Launches application

index-debug.html   Launches application (debug mode)

Rakefile            Rake build file

Frameworks         Copy of /usr/local/share/objj/lib/Frameworks

Resources          Resources (images, etc.) available to application




                                    13                            © 2009 Howard Lewis Ship
Configuration
/*
 * AppController.j
 * example
 *
 * Created by You on July 14, 2009.
 * Copyright 2009, Your Company All rights
reserved.
 */


• capp config key value              Stored in ~/.cappconfig
  • user.name
  • user.email
  • organization.name
  • organization.email
  • organization.url
  • organization.identifier

                                        14                    © 2009 Howard Lewis Ship
View Example App




           15      © 2009 Howard Lewis Ship
Objective-J

              16   © 2009 Howard Lewis Ship
Lineage




          17   © 2009 Howard Lewis Ship
Objective-C




          +                =

       Preprocessor




                      18       © 2009 Howard Lewis Ship
Objective-J Syntax
        Java Syntax                                             Objective-J Syntax

        window.orderFront();                                   [window orderFront];

        icon.moveToXY(100, 200);                               [icon moveToX:100 Y:200];




                                                                 method moveToX:Y:

        Java Syntax                                             Objective-J Syntax

        new JFrame();                                          [[CPWindow alloc] init];

        new JFrame("Toolbox");                                 [[CPWindow alloc] initWithTitle:"Toolbox"];




                                                          Class name
                                                                              Class method

        Java Syntax                                            Objective-J Syntax

        this.setNeedsDisplay(true);                            [self setNeedsDisplay:YES];




Cheat Sheet: this ➠ self, true ➠ YES, false ➠ NO, null ➠ nil        19                              © 2009 Howard Lewis Ship
Defining Classes
                                                Base class
      PageView.j

     @import <AppKit/CPView.j>

     @implementation PageView : CPView
     {
       CALayer _rootLayer;
     }

     // Methods defined here

     @end


                   Convention: instance variables
                   start with underscore




                                      20                     © 2009 Howard Lewis Ship
Defining Methods
- for instance method                 type of parameter
+ for class method
                     PageView.j

                 - (id)initWithFrame:(CGRect)aFrame
                 {
                   self = [super initWithFrame:aFrame];

                     if (self)
  Return type        {
                       _rootLayer = [CALayer layer];
                       [self setWantsLayer:YES];
                       [self setLayer:_rootLayer];
                       [_rootLayer setBackgroundColor:[CPColor whiteColor]];
                       [_rootLayer setNeedsDisplay];
                     }

                     return self;
                 }




                                              21                               © 2009 Howard Lewis Ship
No
Namespaces
    22   © 2009 Howard Lewis Ship
Cappuccino User Interfaces




                                                                          M
                                                                             ac
                                                                                  O
                                                                                      nl
                                                                                         y
                     UI Object properties and connections




                          +                             =
  Controller Class             Interface Builder File        Running User Interface



                                   [CPBundle loadCibNamed:owner:loadDelegate:]
                                   Instantiates & connects




                                           23                             © 2009 Howard Lewis Ship
Actions and Outlets

                                              triggerClicked:




               AppController




@implementation AppController : CPObject
{
    CPWindow    theWindow;
    CPTextField outputField;
}

…

- (void)triggerClicked:(id)sender
{
    [outputField setObjectValue:"You clicked it!"];
}

@end




                                                      24        © 2009 Howard Lewis Ship
capp gen BasicControls -t NibApplication




              25                 © 2009 Howard Lewis Ship
26   © 2009 Howard Lewis Ship
Be 1
                         N

                          ta 5
                           ov
http://280atlas.com/




                 27    © 2009 Howard Lewis Ship
Running as a Web App
Using Maven & Jetty




                      28   © 2009 Howard Lewis Ship
29   © 2009 Howard Lewis Ship
Creating a Web App
• mvn archetype:generate
  • #18 (basic web application)
• Edit pom.xml:
     <plugins>
       <plugin>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>jetty-maven-plugin</artifactId>
         <configuration>
           <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog">
             <append>true</append>
           </requestLog>
         </configuration>
       </plugin>
     </plugins>


• capp gen src/main/webapp/app
• mvn jetty:run
• Open http://localhost:8080/app

                                       30                                © 2009 Howard Lewis Ship
Creating a simple calculator




                31             © 2009 Howard Lewis Ship
Cappuccino Classes
                                    CPObject




                               CPResponder
                      undoManager : CPUndoManager
                              menu : CPMenu
                        nextResponder : CPResponder




                CPView                                CPWindow
             hidden : BOOL                         fullBridge : BOOL
                                                    frame : CGRect
       - addSubview:CPView : void
                                                         level : int
             - display : void
                                                     visible : BOOL
                                                 contentView : CPView
                                               backgroundColor : CPColor
                                                  hasShadow : BOOL
                                                     title : CPString
               CPControl



                                                       CPPanel


                                       32                                  © 2009 Howard Lewis Ship
Cappuccino Classes
                                              CPControl
                                              action : SEL
                                               target: id
                                           enabled : BOOL
                                          highlighted : BOOL
                                            objectValue : id
                                            floatValue: float
                                         doubleValue : double
                                             intValue : int
                                  - initWithFrame:CGFrame : CPControl




                  CPButton                                              CPTextField

               title : CPString                                      editable : BOOL
                                                                      secure: BOOL
             - sizeToFit : void                                      bezeled : BOOL
    + buttonWithTitle:CPString : CPButton
                                                          + labelWithTitle:CPString : CPTextField




                                                    33                                              © 2009 Howard Lewis Ship
Adding Controls




 AppController.j

 - (void)applicationDidFinishLaunching:(CPNotification)aNotification
 {
   var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
                    styleMask:CPBorderlessBridgeWindowMask],
       contentView = [theWindow contentView];

     _display = [CPTextField labelWithTitle:"(placeholder)"];
     [_display setBezeled:YES];
     [_display sizeToFit];

     [contentView addSubview:_display];

     [theWindow orderFront:self];
 }



                                          34                                © 2009 Howard Lewis Ship
Utility Methods

     AppController.j

     - (void)add:(CPView)subview
     {
       [_contentView addSubview:subview];
     }

     - (CPButton)makeButton:value at:(CGRect)frame
     {
       var button = [[CPButton alloc] initWithFrame:frame];

         [button setTitle:value.toString()];

         [self add:button];

         return button;
     }




                                  35                          © 2009 Howard Lewis Ship
More Controls
          AppController.j

             _display = [CPTextField labelWithTitle:"(placeholder)"];
             [_display setFrame:CGRectMake(5, 5, 180, 30)]
             [_display setBezeled:YES];

             [self add:_display];

             [self      makeButton:7 at:CGRectMake(5, 35, 40, 25)];
             [self      makeButton:8 at:CGRectMake(50, 35, 40, 25)];
             [self      makeButton:9 at:CGRectMake(95, 35, 40, 25)];
             [self      makeButton:"*" at:CGRectMake(140, 35, 40, 25)];

             [self      makeButton:4 at:CGRectMake(5, 65, 40, 25)];
             [self      makeButton:5 at:CGRectMake(50, 65, 40, 25)];
             [self      makeButton:6 at:CGRectMake(95, 65, 40, 25)];
             [self      makeButton:"-" at:CGRectMake(140, 65, 40, 25)];

             [self      makeButton:1 at:CGRectMake(5, 95, 40, 25)];
             [self      makeButton:2 at:CGRectMake(50, 95, 40, 25)];
             [self      makeButton:3 at:CGRectMake(95, 95, 40, 25)];
             [self      makeButton:"+" at:CGRectMake(140, 95, 40, 25)];

             [self makeButton:0 at:CGRectMake(5, 125, 85, 25)];
             [self makeButton:"." at:CGRectMake(95, 125, 40, 25)];
             [self makeButton:"=" at:CGRectMake(140, 125, 40, 25)];




                             36                                 © 2009 Howard Lewis Ship
Local vars have no type




                      - (CPButton)makeDigit:(int)value at:(CGRect)frame
                      {
      Should be var     CPButton button = [self makeButton:value at:frame
                                           action:@selector(digit:)];

                          [button setTag:value];

                          return button;
                      }




                              37                               © 2009 Howard Lewis Ship
Local vars have no type




                       - (CPButton)makeDigit:(int)value at:(CGRect)frame
                       {
       Should be var     CPButton button = [self makeButton:value at:frame
                                            action:@selector(digit:)];

                           [button setTag:value];

                           return button;
                       }




      Not helpful!
                               38                               © 2009 Howard Lewis Ship
Client Exception — Safari




                39          © 2009 Howard Lewis Ship
Client Exception — Safari




                40          © 2009 Howard Lewis Ship
Fleshed-Out Calculator
       AppController.j

          _display = [CPTextField labelWithTitle:""];
          [_display setAlignment:CPRightTextAlignment];
          [_display setFrame:CGRectMake(1, 5, 183, 30)]
          [_display setBezeled:YES];

          [self add:_display];

          [self makeButton:"C" atX:0 y:0 action:@selector(clear:)];

          [self      makeButton:"/"    atX:3   y:0   action:@selector(div:)];
          [self      makeButton:"*"    atX:3   y:1   action:@selector(mult:)];
          [self      makeButton:"-"    atX:3   y:2   action:@selector(minus:)];
          [self      makeButton:"+"    atX:3   y:3   action:@selector(plus:)];

          [self makeDigit:7 atX:0 y:1];
          [self makeDigit:8 atX:1 y:1];
          [self makeDigit:9 atX:2 y:1];

          …

          [[self makeButton:"=" atX:3 y:4 action:@selector(compute:)]
           setDefaultButton:YES];




                                  41                                       © 2009 Howard Lewis Ship
Utility Methods
AppController.j

- (CPButton)makeButton:(id)value atX:(int)x y:(int)y action:(SEL)action
{
  var frame = CGRectMake(45 * x + 5, 30 * y + 35, 40, 24);
  var button = [[CPButton alloc] initWithFrame:frame];

    [button setTitle:value.toString()];

    [button setTarget:self];
    [button setAction:action];

    [self add:button];

    return button;
}

- (CPButton)makeDigit:(id)value atX:(int)x y:(int)y
{
  return [self makeButton:value atX:x y:y action:@selector(digit:)];
}




                                          42                              © 2009 Howard Lewis Ship
Action Methods
                           @selector(digit:)

AppController.j

- (void)digit:(CPButton)source
{
  var digit = [source title];

    if (_value == "" && digit == "0") return;

    _value = _sign + _value + digit;
    _sign = "";

    [_display setStringValue:_value];
}

- (void)clear:(id)source
{
  [self reset];
}




                                          43    © 2009 Howard Lewis Ship
Nesting Controllers

            44        © 2009 Howard Lewis Ship
HUD Panel




            45   © 2009 Howard Lewis Ship
Main UI


                                                              Top level window
AppController.j

- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
  var window = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
                                 styleMask:CPBorderlessBridgeWindowMask],
      contentView = [window contentView];

    var button = [CPButton buttonWithTitle:@"Calculator"];

    [button setFrameOrigin:CGPointMake(60, 40)];

    [contentView addSubview:button];

    [button setTarget:self];
    [button setAction:@selector(raiseCalculatorPanel:)];

    [window orderFront:self];
}




                                          46                                © 2009 Howard Lewis Ship
Creating CalcController

     AppController.j

     …
     @import "CalcController.j"

     @implementation AppController : CPObject
     {
       CalcController _calcController;
     }

     …

     - (void)raiseCalculatorPanel:(id)sender
     {
       if (_calcController == nil)
         _calcController = [[CalcController alloc] init];

         [_calcController show];
     }

     @end




                                   47                       © 2009 Howard Lewis Ship
CalcController UI
CalcController.j

- (id)init
{
  self = [super init];

    _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 184, 184)
                 styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask];

    _contentView = [_panel contentView];

    [_panel setTitle:"Calculator"];

    _display = [CPTextField labelWithTitle:""];
    [_display setAlignment:CPRightTextAlignment];
    [_display setFrame:CGRectMake(1, 5, 183, 30)]
    [_display setBezeled:YES];

    [self add:_display];

    [self makeButton:"C" atX:0 y:0 action:@selector(clear:)];

     …

    return self;
}




                                             48                                  © 2009 Howard Lewis Ship
Window Resizing &
Remote Communication
          49      © 2009 Howard Lewis Ship
50   © 2009 Howard Lewis Ship
Twitter Panel UI
TwitterController.j

_panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 245, 184)
   styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask | CPResizableWindowMask];

[_panel setTitle:@"Twitter"];

var label = [CPTextField labelWithTitle:"User:"];
[label setFrame:CGRectMake(3, 7, 50, 24)];
[label setTextColor:[CPColor whiteColor]];

_field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200];

[_field setFrame:CGRectMake(40, 0, 200, 28)];
[_field setTarget:self];
[_field setAction:@selector(startSearch:)];

var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)];

[scrollView setAutohidesScrollers:YES];

var content = [_panel contentView];

[content addSubview:label];
[content addSubview:_field];
[content addSubview:scrollView];




                                            51                                © 2009 Howard Lewis Ship
52   © 2009 Howard Lewis Ship
Autoresize Flags
 Containing CPView

                                        CPViewMinYMargin




                          CPView




                                            HeightSizable
       CPViewMinXMargin                                     CPViewMaxXMargin




                                              CPView
                          CPViewWidthSizable




                                        CPViewMaxYMargin




                                   53                                          © 2009 Howard Lewis Ship
Autoresizing
TwitterController.j

[_panel setTitle:@"Twitter"];
[_panel setMinSize:CGSizeMake(245, 184)];

var label = [CPTextField labelWithTitle:"User:"];
[label setFrame:CGRectMake(3, 7, 50, 24)];
[label setTextColor:[CPColor whiteColor]];

_field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200];

[_field        setFrame:CGRectMake(40, 0, 200, 28)];
[_field        setTarget:self];
[_field        setAction:@selector(startSearch:)];
[_field        setAutoresizingMask:CPViewWidthSizable];

var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)];

[scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];

[scrollView setAutohidesScrollers:YES];
[scrollView setBackgroundColor:[CPColor whiteColor]];




                                                       Temporary

                                                  54                         © 2009 Howard Lewis Ship
55   © 2009 Howard Lewis Ship
CPCollectionView

 TwitterController.j

    var itemPrototype = [[CPCollectionViewItem alloc] init];
    [itemPrototype setView:[[TwitView alloc] init]];

    _timelineView = [[CPCollectionView alloc]
      initWithFrame:CGRectMake(0, 0, CGRectGetWidth(scrollViewBounds) - 2, 0)];
    [_timelineView setItemPrototype:itemPrototype];
    [_timelineView setDelegate:self];
    [_timelineView setMaxNumberOfColumns:1];

    [_timelineView setAutoresizingMask:CPViewWidthSizable];

    [_scrollView setDocumentView:_timelineView];




                                       56                                 © 2009 Howard Lewis Ship
JSON ➠ Image & Label
{
    "title" : "Mmm - biscuits and gravy, in my hometown, with the woman I love.",
    …
    "user" : {
      "profile_image_url" :
          "http://a3.twimg.com/profile_images/71386417/scott_davis_2009_normal.jpg",
      …
    }
}


                    TwitView.j

                    - (void)setRepresentedObject:(JSONObject)obj
                    {
                      if (!_label)
                      {
                        …
                      }

                       [_imageView setImage:[[CPImage alloc]
                         initByReferencingFile:obj.user.profile_image_url
                         size:CPSizeMake(55, 55)]];
                       [_label setStringValue:obj.text];
                    }
                    @end




                                               57                                © 2009 Howard Lewis Ship
Sending the Search Request

                                       Cached file (to avoid authentication)
TwitterController.j

- (void)startSearch:(id)sender
{
  var url = "twitter/statuses/friends_timeline/" + [_field stringValue] + ".json";

    var request = [CPURLRequest requestWithURL:url];
    [CPURLConnection connectionWithRequest:request delegate:self];
}


                                                Who to notify when data arrives




                                           58                                 © 2009 Howard Lewis Ship
Handling the Response


TwitterController.j

- (void)connection:(CPURLConnection)connection didReceiveData:(CPString)data
{
  var timeline = JSON.parse(data);

    [_timelineView setContent:timeline];
}

- (void)connection:(CPURLConnection)connection didFailWithError:(CPString)error
{
  CPLog.error(error);
}


                           TwitView.j

                           - (void)setRepresentedObject:(JSONObject)obj
                           {
                             ...
                           }
                           @end


                                             59                                © 2009 Howard Lewis Ship
Cappuccino
Pitfalls
    60       © 2009 Howard Lewis Ship
Documentation




           61   © 2009 Howard Lewis Ship
Mac-Centric




              62   © 2009 Howard Lewis Ship
Compilation
Exceptions

              63   © 2009 Howard Lewis Ship
Client-Side Efficiency




             64         © 2009 Howard Lewis Ship
Wrap Up

          65   © 2009 Howard Lewis Ship
http://github.com/hlship/nfjs-cappuccino


                    66              © 2009 Howard Lewis Ship
http://cappuccino.org

          67       © 2009 Howard Lewis Ship
Image Credits
  © 2008 nalungaard
  http://www.flickr.com/photos/nalundgaard/2587677285/
                                                      © 2005 Michael Sarver
                       http://www.flickr.com/photos/michaelsarver/44302391/
  © 2007 Till Krech
  http://www.flickr.com/photos/extranoise/487179535/
                                                        © 2009 Phill Davison
                         http://www.flickr.com/photos/phill_dvsn/3771462059/
  © 2007 Howard Gees
  http://www.flickr.com/photos/cyberslayer/952153409/
                                                      © 2006 Tyler Hawkins
                              http://www.flickr.com/photos/m4m/279364376/
  © 2009 Harald
  http://www.flickr.com/photos/haarald/3227728698/
                                                  © 2006 Brittney Bush Bollay
                              http://www.flickr.com/photos/tzofia/247056173/




                                      68                                        © 2009 Howard Lewis Ship

Mais conteúdo relacionado

Mais procurados

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...Chris Richardson
 
Multi level hierarchy
Multi level hierarchyMulti level hierarchy
Multi level hierarchymyrajendra
 
Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19CodelyTV
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmersAlexander Varwijk
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Groovy, Transforming Language
Groovy, Transforming LanguageGroovy, Transforming Language
Groovy, Transforming LanguageUehara Junji
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Stephen Chin
 
Google Developer Fest 2010
Google Developer Fest 2010Google Developer Fest 2010
Google Developer Fest 2010Chris Ramsdale
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free ProgrammingStephen Chin
 
Zend Framework Foundations
Zend Framework FoundationsZend Framework Foundations
Zend Framework FoundationsChuck Reeves
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
Google io bootcamp_2010
Google io bootcamp_2010Google io bootcamp_2010
Google io bootcamp_2010Chris Ramsdale
 

Mais procurados (18)

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
 
Multi level hierarchy
Multi level hierarchyMulti level hierarchy
Multi level hierarchy
 
WCLA12 JavaScript
WCLA12 JavaScriptWCLA12 JavaScript
WCLA12 JavaScript
 
Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014
 
CDI in JEE6
CDI in JEE6CDI in JEE6
CDI in JEE6
 
Groovy, Transforming Language
Groovy, Transforming LanguageGroovy, Transforming Language
Groovy, Transforming Language
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)
 
Google Developer Fest 2010
Google Developer Fest 2010Google Developer Fest 2010
Google Developer Fest 2010
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free Programming
 
Zend Framework Foundations
Zend Framework FoundationsZend Framework Foundations
Zend Framework Foundations
 
intellimeet
intellimeetintellimeet
intellimeet
 
Angular beans
Angular beansAngular beans
Angular beans
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
Google io bootcamp_2010
Google io bootcamp_2010Google io bootcamp_2010
Google io bootcamp_2010
 

Destaque

Animation Restaurant2
Animation Restaurant2Animation Restaurant2
Animation Restaurant2tunk
 
Smart phone development
Smart phone developmentSmart phone development
Smart phone developmentMyles Eftos
 
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansJava Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansIMC Institute
 
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodoการจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web Application : EdmodoNunta Petman
 
Hybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsHybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsPoluru S
 
สร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆสร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆUtain Wongpreaw
 
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04Jenchoke Tachagomain
 
Dream mx
Dream mxDream mx
Dream mxphochai
 
Web Based Application Development with Open Source
Web Based Application Development with Open SourceWeb Based Application Development with Open Source
Web Based Application Development with Open SourceRachabodin Suwannakanthi
 

Destaque (13)

Animation Restaurant2
Animation Restaurant2Animation Restaurant2
Animation Restaurant2
 
Web app
Web appWeb app
Web app
 
Smart phone development
Smart phone developmentSmart phone development
Smart phone development
 
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansJava Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
 
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodoการจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
 
lesson1 JSP
lesson1 JSPlesson1 JSP
lesson1 JSP
 
Hybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsHybrid vs Native vs Web Apps
Hybrid vs Native vs Web Apps
 
Java Web programming Using NetBeans
Java Web programming Using NetBeansJava Web programming Using NetBeans
Java Web programming Using NetBeans
 
สร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆสร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆ
 
lesson4 JSP
lesson4 JSPlesson4 JSP
lesson4 JSP
 
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
 
Dream mx
Dream mxDream mx
Dream mx
 
Web Based Application Development with Open Source
Web Based Application Development with Open SourceWeb Based Application Development with Open Source
Web Based Application Development with Open Source
 

Semelhante a Brew up a Rich Web Application with Cappuccino

Build your operator with the right tool
Build your operator with the right toolBuild your operator with the right tool
Build your operator with the right toolRafał Leszko
 
Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Rafał Leszko
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsHaim Michael
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containersinside-BigData.com
 
Making a small QA system with Docker
Making a small QA system with DockerMaking a small QA system with Docker
Making a small QA system with DockerNaoki AINOYA
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundryrajdeep
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPressHaim Michael
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure ProgrammingHoward Lewis Ship
 
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex HenevaldCloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex Henevaldbuildacloud
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesPavol Pitoňák
 
When Smalltalk Meets the Web
When Smalltalk Meets the WebWhen Smalltalk Meets the Web
When Smalltalk Meets the WebESUG
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache CordovaHazem Saleh
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Chris Ramsdale
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationRob Tweed
 
Docker presentasjon java bin
Docker presentasjon java binDocker presentasjon java bin
Docker presentasjon java binOlve Hansen
 
Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up	Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up droidcon Dubai
 

Semelhante a Brew up a Rich Web Application with Cappuccino (20)

Build your operator with the right tool
Build your operator with the right toolBuild your operator with the right tool
Build your operator with the right tool
 
Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid Applications
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containers
 
Making a small QA system with Docker
Making a small QA system with DockerMaking a small QA system with Docker
Making a small QA system with Docker
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundry
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPress
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure Programming
 
Pyramid deployment
Pyramid deploymentPyramid deployment
Pyramid deployment
 
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex HenevaldCloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
 
Deep Dive - CI/CD on AWS
Deep Dive - CI/CD on AWSDeep Dive - CI/CD on AWS
Deep Dive - CI/CD on AWS
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 
When Smalltalk Meets the Web
When Smalltalk Meets the WebWhen Smalltalk Meets the Web
When Smalltalk Meets the Web
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
 
Cicd.pdf
Cicd.pdfCicd.pdf
Cicd.pdf
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
 
Docker presentasjon java bin
Docker presentasjon java binDocker presentasjon java bin
Docker presentasjon java bin
 
Node.js Workshop
Node.js WorkshopNode.js Workshop
Node.js Workshop
 
Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up	Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up
 

Mais de Howard Lewis Ship

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEBHoward Lewis Ship
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapHoward Lewis Ship
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHoward Lewis Ship
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Howard Lewis Ship
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveHoward Lewis Ship
 
Clojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingClojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingHoward Lewis Ship
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseHoward Lewis Ship
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Howard Lewis Ship
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the UnionHoward Lewis Ship
 
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Howard Lewis Ship
 

Mais de Howard Lewis Ship (16)

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEB
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter Bootstrap
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
 
Clojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingClojure: Towards The Essence of Programming
Clojure: Towards The Essence of Programming
 
Codemash-Clojure.pdf
Codemash-Clojure.pdfCodemash-Clojure.pdf
Codemash-Clojure.pdf
 
Codemash-Tapestry.pdf
Codemash-Tapestry.pdfCodemash-Tapestry.pdf
Codemash-Tapestry.pdf
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting Ease
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)
 
Cascade
CascadeCascade
Cascade
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the Union
 
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
 

Último

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 

Último (20)

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 

Brew up a Rich Web Application with Cappuccino

  • 1. Brew up a Rich Web Application with Cappuccino Howard M. Lewis Ship TWD Consulting hlship@comcast.net 1 © 2009 Howard Lewis Ship
  • 2. Three 'C's, Two 'P's, One 'N' 2 © 2009 Howard Lewis Ship
  • 3. Agenda • Why Cappuccino? • Getting Started • Objective-J • Running as a Web App • Window Resizing & Remote Communication • Cappuccino Pitfalls 3 © 2009 Howard Lewis Ship
  • 4. Why Cappuccino? 4 © 2009 Howard Lewis Ship
  • 5. 5 © 2009 Howard Lewis Ship
  • 6. 6 © 2009 Howard Lewis Ship
  • 7. ❝If you need web applications that offer the same user experience as a desktop app would, then Cappuccino is for you. If you truly believe that the classic web development "components" - the usual HTML/CSS/Javascript horror shop - simply stinks, then you are going to be delighted about Cappuccino, too.❞ Holger Jahn 7 © 2009 Howard Lewis Ship
  • 8. Getting Started 8 © 2009 Howard Lewis Ship
  • 9. Download http://cappuccino.org/download/ Click Here 9 © 2009 Howard Lewis Ship
  • 10. Install Tools sudo ./install-tools 10 © 2009 Howard Lewis Ship
  • 11. Tools Install • Pre-Requisites • Mac or Linux Helps! • Cygwin for Windows • Ruby & Rake •cd Tools ; sudo ./install-tools • Tools & Frameworks installed to /usr/local/share • Must add /usr/local/share/bin to $PATH 11 © 2009 Howard Lewis Ship
  • 12. Create Example capp gen example 12 © 2009 Howard Lewis Ship
  • 13. Generated Files Info.plist Application startup information main.j main() method for application AppController.j Application controller (builds initial UI) index.html Launches application index-debug.html Launches application (debug mode) Rakefile Rake build file Frameworks Copy of /usr/local/share/objj/lib/Frameworks Resources Resources (images, etc.) available to application 13 © 2009 Howard Lewis Ship
  • 14. Configuration /* * AppController.j * example * * Created by You on July 14, 2009. * Copyright 2009, Your Company All rights reserved. */ • capp config key value Stored in ~/.cappconfig • user.name • user.email • organization.name • organization.email • organization.url • organization.identifier 14 © 2009 Howard Lewis Ship
  • 15. View Example App 15 © 2009 Howard Lewis Ship
  • 16. Objective-J 16 © 2009 Howard Lewis Ship
  • 17. Lineage 17 © 2009 Howard Lewis Ship
  • 18. Objective-C + = Preprocessor 18 © 2009 Howard Lewis Ship
  • 19. Objective-J Syntax Java Syntax Objective-J Syntax window.orderFront(); [window orderFront]; icon.moveToXY(100, 200); [icon moveToX:100 Y:200]; method moveToX:Y: Java Syntax Objective-J Syntax new JFrame(); [[CPWindow alloc] init]; new JFrame("Toolbox"); [[CPWindow alloc] initWithTitle:"Toolbox"]; Class name Class method Java Syntax Objective-J Syntax this.setNeedsDisplay(true); [self setNeedsDisplay:YES]; Cheat Sheet: this ➠ self, true ➠ YES, false ➠ NO, null ➠ nil 19 © 2009 Howard Lewis Ship
  • 20. Defining Classes Base class PageView.j @import <AppKit/CPView.j> @implementation PageView : CPView { CALayer _rootLayer; } // Methods defined here @end Convention: instance variables start with underscore 20 © 2009 Howard Lewis Ship
  • 21. Defining Methods - for instance method type of parameter + for class method PageView.j - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; if (self) Return type { _rootLayer = [CALayer layer]; [self setWantsLayer:YES]; [self setLayer:_rootLayer]; [_rootLayer setBackgroundColor:[CPColor whiteColor]]; [_rootLayer setNeedsDisplay]; } return self; } 21 © 2009 Howard Lewis Ship
  • 22. No Namespaces 22 © 2009 Howard Lewis Ship
  • 23. Cappuccino User Interfaces M ac O nl y UI Object properties and connections + = Controller Class Interface Builder File Running User Interface [CPBundle loadCibNamed:owner:loadDelegate:] Instantiates & connects 23 © 2009 Howard Lewis Ship
  • 24. Actions and Outlets triggerClicked: AppController @implementation AppController : CPObject { CPWindow theWindow; CPTextField outputField; } … - (void)triggerClicked:(id)sender { [outputField setObjectValue:"You clicked it!"]; } @end 24 © 2009 Howard Lewis Ship
  • 25. capp gen BasicControls -t NibApplication 25 © 2009 Howard Lewis Ship
  • 26. 26 © 2009 Howard Lewis Ship
  • 27. Be 1 N ta 5 ov http://280atlas.com/ 27 © 2009 Howard Lewis Ship
  • 28. Running as a Web App Using Maven & Jetty 28 © 2009 Howard Lewis Ship
  • 29. 29 © 2009 Howard Lewis Ship
  • 30. Creating a Web App • mvn archetype:generate • #18 (basic web application) • Edit pom.xml: <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog"> <append>true</append> </requestLog> </configuration> </plugin> </plugins> • capp gen src/main/webapp/app • mvn jetty:run • Open http://localhost:8080/app 30 © 2009 Howard Lewis Ship
  • 31. Creating a simple calculator 31 © 2009 Howard Lewis Ship
  • 32. Cappuccino Classes CPObject CPResponder undoManager : CPUndoManager menu : CPMenu nextResponder : CPResponder CPView CPWindow hidden : BOOL fullBridge : BOOL frame : CGRect - addSubview:CPView : void level : int - display : void visible : BOOL contentView : CPView backgroundColor : CPColor hasShadow : BOOL title : CPString CPControl CPPanel 32 © 2009 Howard Lewis Ship
  • 33. Cappuccino Classes CPControl action : SEL target: id enabled : BOOL highlighted : BOOL objectValue : id floatValue: float doubleValue : double intValue : int - initWithFrame:CGFrame : CPControl CPButton CPTextField title : CPString editable : BOOL secure: BOOL - sizeToFit : void bezeled : BOOL + buttonWithTitle:CPString : CPButton + labelWithTitle:CPString : CPTextField 33 © 2009 Howard Lewis Ship
  • 34. Adding Controls AppController.j - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; _display = [CPTextField labelWithTitle:"(placeholder)"]; [_display setBezeled:YES]; [_display sizeToFit]; [contentView addSubview:_display]; [theWindow orderFront:self]; } 34 © 2009 Howard Lewis Ship
  • 35. Utility Methods AppController.j - (void)add:(CPView)subview { [_contentView addSubview:subview]; } - (CPButton)makeButton:value at:(CGRect)frame { var button = [[CPButton alloc] initWithFrame:frame]; [button setTitle:value.toString()]; [self add:button]; return button; } 35 © 2009 Howard Lewis Ship
  • 36. More Controls AppController.j _display = [CPTextField labelWithTitle:"(placeholder)"]; [_display setFrame:CGRectMake(5, 5, 180, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:7 at:CGRectMake(5, 35, 40, 25)]; [self makeButton:8 at:CGRectMake(50, 35, 40, 25)]; [self makeButton:9 at:CGRectMake(95, 35, 40, 25)]; [self makeButton:"*" at:CGRectMake(140, 35, 40, 25)]; [self makeButton:4 at:CGRectMake(5, 65, 40, 25)]; [self makeButton:5 at:CGRectMake(50, 65, 40, 25)]; [self makeButton:6 at:CGRectMake(95, 65, 40, 25)]; [self makeButton:"-" at:CGRectMake(140, 65, 40, 25)]; [self makeButton:1 at:CGRectMake(5, 95, 40, 25)]; [self makeButton:2 at:CGRectMake(50, 95, 40, 25)]; [self makeButton:3 at:CGRectMake(95, 95, 40, 25)]; [self makeButton:"+" at:CGRectMake(140, 95, 40, 25)]; [self makeButton:0 at:CGRectMake(5, 125, 85, 25)]; [self makeButton:"." at:CGRectMake(95, 125, 40, 25)]; [self makeButton:"=" at:CGRectMake(140, 125, 40, 25)]; 36 © 2009 Howard Lewis Ship
  • 37. Local vars have no type - (CPButton)makeDigit:(int)value at:(CGRect)frame { Should be var CPButton button = [self makeButton:value at:frame action:@selector(digit:)]; [button setTag:value]; return button; } 37 © 2009 Howard Lewis Ship
  • 38. Local vars have no type - (CPButton)makeDigit:(int)value at:(CGRect)frame { Should be var CPButton button = [self makeButton:value at:frame action:@selector(digit:)]; [button setTag:value]; return button; } Not helpful! 38 © 2009 Howard Lewis Ship
  • 39. Client Exception — Safari 39 © 2009 Howard Lewis Ship
  • 40. Client Exception — Safari 40 © 2009 Howard Lewis Ship
  • 41. Fleshed-Out Calculator AppController.j _display = [CPTextField labelWithTitle:""]; [_display setAlignment:CPRightTextAlignment]; [_display setFrame:CGRectMake(1, 5, 183, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:"C" atX:0 y:0 action:@selector(clear:)]; [self makeButton:"/" atX:3 y:0 action:@selector(div:)]; [self makeButton:"*" atX:3 y:1 action:@selector(mult:)]; [self makeButton:"-" atX:3 y:2 action:@selector(minus:)]; [self makeButton:"+" atX:3 y:3 action:@selector(plus:)]; [self makeDigit:7 atX:0 y:1]; [self makeDigit:8 atX:1 y:1]; [self makeDigit:9 atX:2 y:1]; … [[self makeButton:"=" atX:3 y:4 action:@selector(compute:)] setDefaultButton:YES]; 41 © 2009 Howard Lewis Ship
  • 42. Utility Methods AppController.j - (CPButton)makeButton:(id)value atX:(int)x y:(int)y action:(SEL)action { var frame = CGRectMake(45 * x + 5, 30 * y + 35, 40, 24); var button = [[CPButton alloc] initWithFrame:frame]; [button setTitle:value.toString()]; [button setTarget:self]; [button setAction:action]; [self add:button]; return button; } - (CPButton)makeDigit:(id)value atX:(int)x y:(int)y { return [self makeButton:value atX:x y:y action:@selector(digit:)]; } 42 © 2009 Howard Lewis Ship
  • 43. Action Methods @selector(digit:) AppController.j - (void)digit:(CPButton)source { var digit = [source title]; if (_value == "" && digit == "0") return; _value = _sign + _value + digit; _sign = ""; [_display setStringValue:_value]; } - (void)clear:(id)source { [self reset]; } 43 © 2009 Howard Lewis Ship
  • 44. Nesting Controllers 44 © 2009 Howard Lewis Ship
  • 45. HUD Panel 45 © 2009 Howard Lewis Ship
  • 46. Main UI Top level window AppController.j - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var window = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [window contentView]; var button = [CPButton buttonWithTitle:@"Calculator"]; [button setFrameOrigin:CGPointMake(60, 40)]; [contentView addSubview:button]; [button setTarget:self]; [button setAction:@selector(raiseCalculatorPanel:)]; [window orderFront:self]; } 46 © 2009 Howard Lewis Ship
  • 47. Creating CalcController AppController.j … @import "CalcController.j" @implementation AppController : CPObject { CalcController _calcController; } … - (void)raiseCalculatorPanel:(id)sender { if (_calcController == nil) _calcController = [[CalcController alloc] init]; [_calcController show]; } @end 47 © 2009 Howard Lewis Ship
  • 48. CalcController UI CalcController.j - (id)init { self = [super init]; _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 184, 184) styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask]; _contentView = [_panel contentView]; [_panel setTitle:"Calculator"]; _display = [CPTextField labelWithTitle:""]; [_display setAlignment:CPRightTextAlignment]; [_display setFrame:CGRectMake(1, 5, 183, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:"C" atX:0 y:0 action:@selector(clear:)]; … return self; } 48 © 2009 Howard Lewis Ship
  • 49. Window Resizing & Remote Communication 49 © 2009 Howard Lewis Ship
  • 50. 50 © 2009 Howard Lewis Ship
  • 51. Twitter Panel UI TwitterController.j _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 245, 184) styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask | CPResizableWindowMask]; [_panel setTitle:@"Twitter"]; var label = [CPTextField labelWithTitle:"User:"]; [label setFrame:CGRectMake(3, 7, 50, 24)]; [label setTextColor:[CPColor whiteColor]]; _field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200]; [_field setFrame:CGRectMake(40, 0, 200, 28)]; [_field setTarget:self]; [_field setAction:@selector(startSearch:)]; var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)]; [scrollView setAutohidesScrollers:YES]; var content = [_panel contentView]; [content addSubview:label]; [content addSubview:_field]; [content addSubview:scrollView]; 51 © 2009 Howard Lewis Ship
  • 52. 52 © 2009 Howard Lewis Ship
  • 53. Autoresize Flags Containing CPView CPViewMinYMargin CPView HeightSizable CPViewMinXMargin CPViewMaxXMargin CPView CPViewWidthSizable CPViewMaxYMargin 53 © 2009 Howard Lewis Ship
  • 54. Autoresizing TwitterController.j [_panel setTitle:@"Twitter"]; [_panel setMinSize:CGSizeMake(245, 184)]; var label = [CPTextField labelWithTitle:"User:"]; [label setFrame:CGRectMake(3, 7, 50, 24)]; [label setTextColor:[CPColor whiteColor]]; _field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200]; [_field setFrame:CGRectMake(40, 0, 200, 28)]; [_field setTarget:self]; [_field setAction:@selector(startSearch:)]; [_field setAutoresizingMask:CPViewWidthSizable]; var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)]; [scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; [scrollView setAutohidesScrollers:YES]; [scrollView setBackgroundColor:[CPColor whiteColor]]; Temporary 54 © 2009 Howard Lewis Ship
  • 55. 55 © 2009 Howard Lewis Ship
  • 56. CPCollectionView TwitterController.j var itemPrototype = [[CPCollectionViewItem alloc] init]; [itemPrototype setView:[[TwitView alloc] init]]; _timelineView = [[CPCollectionView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(scrollViewBounds) - 2, 0)]; [_timelineView setItemPrototype:itemPrototype]; [_timelineView setDelegate:self]; [_timelineView setMaxNumberOfColumns:1]; [_timelineView setAutoresizingMask:CPViewWidthSizable]; [_scrollView setDocumentView:_timelineView]; 56 © 2009 Howard Lewis Ship
  • 57. JSON ➠ Image & Label { "title" : "Mmm - biscuits and gravy, in my hometown, with the woman I love.", … "user" : { "profile_image_url" : "http://a3.twimg.com/profile_images/71386417/scott_davis_2009_normal.jpg", … } } TwitView.j - (void)setRepresentedObject:(JSONObject)obj { if (!_label) { … } [_imageView setImage:[[CPImage alloc] initByReferencingFile:obj.user.profile_image_url size:CPSizeMake(55, 55)]]; [_label setStringValue:obj.text]; } @end 57 © 2009 Howard Lewis Ship
  • 58. Sending the Search Request Cached file (to avoid authentication) TwitterController.j - (void)startSearch:(id)sender { var url = "twitter/statuses/friends_timeline/" + [_field stringValue] + ".json"; var request = [CPURLRequest requestWithURL:url]; [CPURLConnection connectionWithRequest:request delegate:self]; } Who to notify when data arrives 58 © 2009 Howard Lewis Ship
  • 59. Handling the Response TwitterController.j - (void)connection:(CPURLConnection)connection didReceiveData:(CPString)data { var timeline = JSON.parse(data); [_timelineView setContent:timeline]; } - (void)connection:(CPURLConnection)connection didFailWithError:(CPString)error { CPLog.error(error); } TwitView.j - (void)setRepresentedObject:(JSONObject)obj { ... } @end 59 © 2009 Howard Lewis Ship
  • 60. Cappuccino Pitfalls 60 © 2009 Howard Lewis Ship
  • 61. Documentation 61 © 2009 Howard Lewis Ship
  • 62. Mac-Centric 62 © 2009 Howard Lewis Ship
  • 63. Compilation Exceptions 63 © 2009 Howard Lewis Ship
  • 64. Client-Side Efficiency 64 © 2009 Howard Lewis Ship
  • 65. Wrap Up 65 © 2009 Howard Lewis Ship
  • 66. http://github.com/hlship/nfjs-cappuccino 66 © 2009 Howard Lewis Ship
  • 67. http://cappuccino.org 67 © 2009 Howard Lewis Ship
  • 68. Image Credits © 2008 nalungaard http://www.flickr.com/photos/nalundgaard/2587677285/ © 2005 Michael Sarver http://www.flickr.com/photos/michaelsarver/44302391/ © 2007 Till Krech http://www.flickr.com/photos/extranoise/487179535/ © 2009 Phill Davison http://www.flickr.com/photos/phill_dvsn/3771462059/ © 2007 Howard Gees http://www.flickr.com/photos/cyberslayer/952153409/ © 2006 Tyler Hawkins http://www.flickr.com/photos/m4m/279364376/ © 2009 Harald http://www.flickr.com/photos/haarald/3227728698/ © 2006 Brittney Bush Bollay http://www.flickr.com/photos/tzofia/247056173/ 68 © 2009 Howard Lewis Ship