Cappuccino: zobrazujeme tabulku s daty

Minule jsme se naučili pracovat s uživatelským rozhraním a jeho základními prvky. Vytvořili jsme si jednoduchou aplikaci, která nám umožnila přidat položku z textového pole do pole CPArray. A v dnešním díle si naší aplikaci vylepšíme o možnost zobrazení záznamů v tabulce.
Seriál: Vývoj aplikací v Cappuccinu (4 díly)
- Cappuccino – webové aplikace snadno a rychle 4. 10. 2010
- Základy Objective-J: syntaxe a framework Foundation 18. 10. 2010
- Cappuccino: uživatelské rozhraní aplikace a AppKit 11. 11. 2010
- Cappuccino: zobrazujeme tabulku s daty 1. 12. 2010
Nálepky:
Čeho chceme dosáhnout
V dnešním díle můžeme s naší jednoduchou aplikací, kterou jsme si vytvořili v minulém díle, pokračovat a rozvíjet ji.
Podstatnou částí většiny webových aplikací je rozumná forma výpisu dat, v našem případě se zaměříme na výpis úkolů do tabulky.
Naše aplikace bude vypadat v závěru takto:
Co k tomu budeme potřebovat
Začneme odděleným příkladem jednoduché tabulky, kterou následně na naší aplikaci napojíme.
CPTableView
Třída, která nám umožní pracovat s tabulkou se jmenuje CPTableView. Jak jsme si ale v prvním díle seriálu řekli, oficiální dokumentace nám toho příliš nepoví, proto doporučuji přečíst referenci k třídě NSTableView.
Příklad – tabulka
Začneme vygenerováním nového projektu pro oddělenou implementaci tabulky:
a pročištěním kódu:
@import @implementation AppController : CPObject { } - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; //kód příkladu tabulky [theWindow orderFront:self]; } @end
Náš příklad s tabulkou bude ve finále vypadat takto:
Třída CPTableView sama o sobě nezná způsob jak scrollovat, proto jí musíme umístit dovnitř další třídy CPScrollView, která ví, jak na to. Nové scrollView vytvoříme následovně:
var scrollView = [[CPScrollView alloc] initWithFrame: CGRectMake(50.0,50.0,150.0,200.0)]; [scrollView setAutoresizingMask: CPViewWidthSizable | CPViewHeightSizable];
Ve chvíli, kdy již máme prvek, uvnitř kterého se dá scrollovat, můžeme přejít k vytvoření samotné CPTableView
, kterou nastavíme tak, aby rozměry přesně odpovídala CPScrollView
:
tableView = [[CPTableView alloc] initWithFrame: [scrollView bounds]];
Třída CPTableView
, resp. naše tabulka bude mít zdroj dat. Tímto zdrojem bude pole definované jako instanční proměnná – stejně jako v minulém díle. Nastavíme tedy zdroj dat tabulky na self – odkaz na naší třídu AppController.
[tableView setDataSource:self];
Vytvoříme nový sloupeček tabulky a ten následně do tabulky přidáme:
var column = [[CPTableColumn alloc] initWithIdentifier:@"Browsers"]; [[column headerView] setStringValue:@"Browser"]; [column setWidth:140.0]; [tableView addTableColumn:column];
Důležitým krokem je nastavení potomka prvku pro CPScrollView
. K samotnému uživatelskému rozhraní je to vše a můžeme tabulku přidat do View celé naší aplikace:
[scrollView setDocumentView:tableView]; [contentView addSubview:scrollView];
Bohužel to ještě není vše, co je potřeba udělat pro zprovoznění tableView
, existují 2 metody, které musíme implementovat.
Metoda numberOfRowsInTableView
nám vrací počet položek v tabulce.
A metoda tableView:objectValueForTableColumn:row:
nám přesně určuje, který záznam se v řádku pro daný sloupec zobrazí.
Tyto dvě metody přidáme kamkoliv před ukončovací symbol @end
.
- (int)numberOfRowsInTableView:(CPTableView)aTableView { return [browsers count]; } - (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow { return [browsers[aRow]]; }
Poslední věcí, o kterou se v našem příkladu musíme postarat jsou samotná data. Vytvoříme si podobné pole jako v minulém díle, jen s tím rozdílem, že si do něj naházíme názvy prohlížečů:
browsers = [[CPArray alloc] init]; [browsers addObject:@"Google Chrome"]; [browsers addObject:@"Apple Safari"]; [browsers addObject:@"Mozilla FireFox"]; [browsers addObject:@"Internet Explorer"];
Stejně jako v minulém díle budeme pracovat s polem mimo metodu applicationDidFinishLaunching
, takže jej musíme zpřístupnit pro jakoukoliv metodu dané třídy – udělat z něj instanční proměnnou.
@implementation AppController : CPObject { CPArray browsers; }
Funkční kód vypadá dohromady takto:
@import @implementation AppController : CPObject { CPArray browsers; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; browsers = [[CPArray alloc] init]; [browsers addObject:@"Google Chrome"]; [browsers addObject:@"Apple Safari"]; [browsers addObject:@"Mozilla FireFox"]; [browsers addObject:@"Internet Explorer"]; var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(50.0,50.0,150.0,200.0)]; [scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; var tableView = [[CPTableView alloc] initWithFrame:[scrollView bounds]]; [tableView setDataSource:self]; var column = [[CPTableColumn alloc] initWithIdentifier:@"Browsers"]; [[column headerView] setStringValue:@"Browser"]; [column setWidth:140.0]; [tableView addTableColumn:column]; [scrollView setDocumentView:tableView]; [contentView addSubview:scrollView]; [theWindow orderFront:self]; } - (int)numberOfRowsInTableView:(CPTableView)aTableView { return [browsers count]; } - (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow { return [browsers[aRow]]; } @end
Napojení tabulky na ToDo aplikaci
Můžeme pokračovat s kódem, s kterým jsme skončili v minulém díle:
@import <Foundation/CPObject.j> @implementation AppController : CPObject { CPTextField textField; CPMutableArray todo; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; todo = [[CPArray alloc] init]; [todo addObject:@"Koupit rohlíky"]; [todo addObject:@"Napsat článek pro zdroják"]; var button = [[CPButton alloc] initWithFrame: CGRectMake(230.0,37.0,80.0,24.0)]; [button setTitle:@"přidat"]; [button setTarget:self]; [button setAction:@selector(addItem:)]; textField = [CPTextField textFieldWithStringValue:@"" placeholder:@"Úkol" width:200.0]; [textField setFrameOrigin:CGPointMake(30.0, 35.0)]; [contentView addSubview:textField]; [contentView addSubview:button]; [theWindow orderFront:self]; } - (void)logIt:(id)sender { console.log(@"-------"); console.log(@"vypiš položky"); for (var i = 0; i < todo.length; i++) { console.log([todo objectAtIndex: i]); } } - (void)addItem:(id)sender { [todo addObject: [textField stringValue]]; [self logIt:sender]; } @end
Po drobnějších úpravách, aplikování metod a tříd, které jsme se dnes naučili používat, dosáhneme funkčního todo listu s výpisem položek do tabulky:
@import @implementation AppController : CPObject { CPTextField textField; CPMutableArray todo; CPTableView tableView; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; //data source - array todo = [[CPArray alloc] init]; [todo addObject:@"Koupit rohlíky"]; [todo addObject:@"Napsat článek pro zdroják"]; var button = [[CPButton alloc] initWithFrame: CGRectMake(230.0,37.0,80.0,24.0)]; [button setTitle:@"přidat"]; [button setTarget:self]; [button setAction:@selector(addItem:)]; //textField textField = [CPTextField textFieldWithStringValue:@"" placeholder:@"Úkol" width:200.0]; [textField setFrameOrigin:CGPointMake(30.0, 35.0)]; //scrollView, tableView var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(34.0,80.0,280.0,200.0)]; tableView = [[CPTableView alloc] initWithFrame:[scrollView bounds]]; [tableView setDataSource:self]; var column = [[CPTableColumn alloc] initWithIdentifier:@"Tasks"]; [[column headerView] setStringValue:@"Task"]; [column setWidth:210.0]; [tableView addTableColumn:column]; [scrollView setDocumentView:tableView]; //adding views - show [contentView addSubview:scrollView]; [contentView addSubview:textField]; [contentView addSubview:button]; [theWindow orderFront:self]; } - (void)addItem:(id)sender { [todo addObject: [textField stringValue]]; [tableView reloadData]; } -(int)numberOfRowsInTableView:(CPTableView)aTableView { return [todo count]; } -(id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow { return [todo[aRow]]; } @end
Co jsme se naučili
Dnes jsme si rozšířili znalosti uživatelského rozhraní frameworku Cappuccino o výpis dat do tabulky a ukázali si praktické použití této tabulky v naší aplikaci.
Co bude příště
V příštím díle si ukážeme napojení na backend a komunikaci se serverem prostřednictvím JSONu.
Bude další díl? Bral bych nějakého jednoduchého Twitter klienta. Nebo napojení na server-side technologii (byl jsi na Rails školení, tak proč to nezúročit :-) )
Ahoj Lukáši, mohl bych menší dotazy? Chápu správně, že [scrollView setDocumentView:tableView]; zajišťuje to, že tableView je potomkem scrollView? A můžeš prosím osvětlit metodu:
-(id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow
{
return [todo[aRow]];
}
Pokud to chápu správně, bere si to parametry – tabulku, sloupec tabulky a řádek. A vrací to hodnotu toho řádku? Účel téhle metody?
Předem díky za odpověď, ObjectiveC-like syntaxe je pro mě nová ;-)