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á ;-)