Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Informace
K vašim službám 5: stále vyhrazeno pro programátory
macosearly
18. prosince 2001, 00.00 | Minule jsme si slíbili kompletní aplikaci, která umožní prohlížení složek a souborů, a která bude plně podporovat (mj.) souborové služby. Není to nic těžkého — jen se podívejme.
K vašim službám 5: stále vyhrazeno pro programátoryMinule jsme si slíbili kompletní aplikaci, která umožní prohlížení složek a souborů, a která bude plně podporovat (mj.) souborové služby. Není to nic těžkého — jen se podívejme:
Projekt
Ačkoli nový ProjectBuilder není ani zdaleka tak pohodlný, jako býval původní ProjectBuilder z OpenStepu, na to, co potřebujeme dnes, jeho služby nejsou nijak zapeklité: prostě si vyžádáme vytvoření nového projektu typu "Cocoa Application".
Nejprve připravíme uživatelské rozhraní
V přehledu souborů otevřeme skupinu "Resources" a poklepáním otevřeme soubor "MainMenu.nib", který obsahuje základní GUI nově vytvářené aplikace:
ProjectBuilder automaticky spustí aplikaci InterfaceBuilder, a v té provedeme následující kroky:
Příprava browseru pro zobrazení dat
V InterfaceBuilderu vidíme, že systém pro nás už připravil základní okno aplikace; víc jich potřebovat ani nebudeme. Jen do okna umístíme browser, ve kterém budeme zobrazovat složky a soubory.
Najdeme paletu připravených objektů (pokud není vidět, zobrazíme ji příkazem "Tools / Palettes / Show Palettes"), a v ní přepneme na skupinu "Cocoa Data Views" — standardně je v okně palet na pátém místě, a její ikona vypadá jako textový editor. Z této skupiny vybereme browser — je v pravém dolním rohu — a vhodíme jej do okna:
Browser myší roztáhneme tak, aby zabral celé okno, a použijeme inspektor pro nastavení jeho atributů. Inspektor otevřeme příkazem "Tools / Show Info" (v OS X je pro vetší zmatení pojmů nyní v módě říkat inspektorům "info panely"); v jeho horní části je pop-up menu, které přapíná mezi různými režimy. My použijeme zatím režimy "Attributes" a "Size" pro nastavení požadovaného chování browseru:
Objekt, který řídí aplikaci
V korektně navržené objektové aplikaci je obvykle jeden objekt, který řídí aplikaci — na jedné straně interpretuje požadavky uživatele a řídí zobrazení dat v GUI, na straně druhé přistupuje k "datovému modelu" aplikace.
Nejinak tomu bude u nás: připravíme objekt třídy Controller, který bude celou aplikaci řídit. I to můžeme udělat přímo v InterfaceBuilderu: nejprve přepneme hlavní okno InterfaceBuilderu do režimu Classes, a tam nalezneme třídu NSObject. Nad ní použijeme kontextové pop-up menu (pravá klávesa myši, nebo Control-klepnutí pro nešťastníky, kteří mají myš s jediným tlačítkem), a z něj vybereme příkaz "Subclass NSObject"; InterfaceBuilder vytvoří a označí novou třídu MyObject:
Použijeme opět inspektor (v režimu "Attributes"), abychom třídu přejmenovali na "Controller", a abychom do ní přidali jeden "outlet" se jménem "browser". Outlety jsou odkazy na jiné objekty; my budeme potřebovat, aby náš controller měl k dispozici odkaz na browser, a ten jsme se právě připravili.
Nyní musíme zajistit
- aby zdrojové soubory, obsahující implementaci controlleru, byly k dispozici v ProjectBuilderu. Toho docílíme tak, že v hlavním okně InterfaceBuilderu nad třídou Controller použijeme opět kontextové pop-up menu, a z něj zvolíme příkaz "Create Files for Controller" (a následující dialog prostě potvrdíme tlačítkem "Choose");
- aby skutečně existoval objekt třídy Controller. Toho docílíme tak, že v tomtéž kontextovém pop-up menu zvolíme příkaz "Instantiate Controller".
Potřebná propojení
Nesmíme zapomenout, že v controlleru sice máme outlet "browser", ale ještě jsme se nepostarali o to, aby jeho obsahem byl skutečně odkaz na browser, který jsme hned na začátku umístili do okna. Na to (a na podobné účely) máme v InterfaceBuilderu "dráty": kterékoli dva objekty můžeme propojit tak, že mezi nimi natáhneme "drát" myší, přidržíme-li zároveň přapínač Control; v inspektoru "Connections" pak zvolíme, jaké propojení máme na mysli.
Pro naši aplikaci potřebujeme propojení tři:
- z controlleru (který se nám po poslední akci "Instantiate..." objevil v hlavním okně jako modrá krychlička) natáhneme drát na browser, a v inspektoru zvolíme náš outlet "browser";
- z ikonky "File's Owner" natáhneme drát na controller, a v inspektoru vybereme outlet "delegate" — tak zajistíme, že controller bude zapojen do "responder chainu", a můžeme v něm implementovat metody pro práci se Services (viz minulý díl seriálu);
- z browseru natáhneme drát na controller, a opět zvolíme outlet "delegate". Tím zajistíme, že browser si od controlleru vyžádá data, jež bude zobrazovat.
Následující obrázek ilustruje první "prodrátování"; druhá dvě jsou stejně jednoduchá:
Stačí dopsat pár metod...
S GUI jsme hotovi, musíme jen dopsat pát zbylých metod
- pro zobrazení složek a souborů v browseru;
- pro podporu Services.
Zobrazení složek a souborů
Vzhledem k tomu, že se nejedná o hlavní téma našeho seriálu, projdeme tuto část jen velmi rychle:
- do souboru Controller.h přidáme vedle outletu "browser" (který tam už samozřejmě je) novou proměnnou "fm": do ní za chvilku uložíme objekt třídy NSFileManager, který nám zajistí přístup k souborům;
- v souboru Controller.m opět použijeme metodu awakeFromNib pro inicializaci (zatím v ní jen naplníme proměnnou "fm");
- přidáme metodu browser:numberOfRowsInColumn:, jejímž prostřednictvím se browser svého delegáta ptá, kolik má být řádků v daném sloupci. Implementace prostě zjistí od file manageru počet objektů na odpovídající cestě, a ten vrátí;
- přidáme metodu browser:willDisplayCell:atRow:column: — tu browser používá pro určení hodnoty pro konkrétní položku. My si prostě vyžádáme odpovídající soubor nebo složku od file manageru, a jméno uložíme do browseru. Navíc zjistíme, jde-li o soubor nebo složku, a podle toho určíme atribut "leaf" (list).
Oba soubory nyní vypadají takto:
// Controller.h
#import <Cocoa/Cocoa.h>
@interface Controller : NSObject {
IBOutlet id browser;
id fm;
}
@end
//Controller.m
#import "Controller.h"
@implementation Controller
-(void)awakeFromNib {
fm=[NSFileManager defaultManager];
}
-(int)browser:(NSBrowser*)sender numberOfRowsInColumn:(int)column {
NSString *path=column?[sender pathToColumn:column]:@"/";
return [[fm directoryContentsAtPath:path] count];
}
-(void)browser:(NSBrowser*)sender willDisplayCell:(id)cell
atRow:(int)row column:(int)column {
NSString *path=column?[sender pathToColumn:column]:@"/";
NSString *component=[[fm directoryContentsAtPath:path] objectAtIndex:row];
NSDictionary *attrib=[fm fileAttributesAtPath:
[path stringByAppendingPathComponent:component] traverseLink:YES];
[cell setTitle:component];
[cell setLeaf:![[attrib objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory]];
}
@end
Nyní už můžeme browser používat pro prohlížení systému složek a souborů (mimochodem, zkuste to! Nestačíte se divit, jak nepřesnou představu o tom, jaké složky a soubory jsou skutečně k dispozici a pod jakými jmény dává Finder!). Chybí však zatím to hlavní, kvůli čemu jsme se do celé práce pouštěli: podpora služeb.
Podpora Services
Podpora Services však je poměrně jednoduchá. Připomeňme z minulého dílu, že stačí zařídit tři věci:
- na začátku se aplikace zaregistruje se všemi datovými typy, nad nimiž má pro ni smysl vůbec Services využívat;
- implementovat metodu validRequestorForSendType:returnType: pro zjištění, jaká data jsou momentálně k dispozici;
- implementovat metodu writeSelectionToPasteboard:types: pro odeslání dat.
Vzhledem k tomu, že jsme zapojili náš controller do responder chainu (připojením na outlet "delegate" objektu "File's Owner"), můžeme vše implementovat přímo v něm. Pro zajištění prvého bodu prostě stačí přidat do metody awakeFromNib řádek
[NSApp registerServicesMenuSendTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
returnTypes:nil];
I metoda validRequestorForSendType:returnType: je triviální — jen ověříme požadovaný typ, a zjistíme, je-li vůbec něco v browseru označeno:
-(id)validRequestorForSendType:(NSString*)sendType returnType:(NSString*)returnType {
if ([sendType isEqual:NSFilenamesPboardType] && [browser selectedCell])
return self;
return nil;
}
Malinko složitější je jen poslední metoda, writeSelectionToPasteboard:types:. Příčinou je to, že v browseru může být označeno libovolně mnoho objektů najednou, a my samozřejmě musíme systému služeb předat všechny. Proto je zapotřebí nejprve pomocí NSEnumeratoru připravit seznam všech označených objektů, a pak teprve jej již známým způsobem předat dál. I tak nám na ni stačí přibližně deset řádků:
-(BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
if ([types containsObject:NSFilenamesPboardType] && [browser selectedCell]) {
NSString *rootPath=[[browser path] stringByDeletingLastPathComponent];
NSMutableArray *selectedFiles=[NSMutableArray array];
NSEnumerator *en=[[browser selectedCells] objectEnumerator];
NSCell *cell;
while (cell=[en nextObject])
[selectedFiles addObject:
[rootPath stringByAppendingPathComponent:[cell title]]];
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
return [pboard setPropertyList:selectedFiles forType:NSFilenamesPboardType];
}
return NO;
}
To je už opravdu vše: můžeme aplikaci zbuildovat a vyzkoušet — hned máme k dispozici např. služby pro archivaci souborů:
(Mimochodem, podpora tear-off menu stále není standardní součástí OSX; protože však bez ní je OSX zhola nepoužitelný, napsal jsem si na to hack, který aspoň zčásti vrací skvělé vlastnosti GUI NeXTStepu.)
Ti, kdo by snad s postupnou tvorbou aplikace měli potíže, naleznou kompletní projekt, připravený přesně popsaným postupem, na www.ocs.cz/Apps/MiniWM.tar.gz.
Příště...
...už seriál opravdu ukončíme tím, že si ukážeme, jak naprogramovat poskytování služeb ostatním aplikacím.
Obsah seriálu (více o seriálu):
- Mac OS X - příjezd na čas
- Mac OS X - Instalace
- Mac OS X prakticky 1.
- Mac OS X - podpora českého prostředí
- Mac OS X - tak trochu utajený update
- Mac OS X prakticky 2.
- Mac OS nebo X?
- Mac OS X pro všechny - nyní i v Čechách
- Hledá se majitel souboru!
- Mac OS X - domovská složka a plocha
- Mac OS X - pohled do základů
- Mac OS X - uživatelské rozhraní zblízka, 1. část
- Mac OS X - uživatelské prostředí zblízka, 2. část
- Mac OS X - uživatelské prostředí zblízka, 3. část
- Mac OS X: uživatelské prostředí zblízka 4
- Novinky v Mac OS X 10.1, 1. část
- Novinky v Mac OS X 10.1, 2. část
- Mac OS X v síti...
- Novinky v Mac OS X, 3. část -jak se tiskne...
- Mac OS X pod kapotou - resources
- NetInfo - síťové centrum Mac OS X
- Uložení dat v NetInfu, aneb stromy ve stromech
- K vašim službám...
- ColorSync 4 - krok k Microsoftu?
- NetInfoManager, aneb přímá cesta do databáze
- K vašim službám 2: co nabízí Apple
- Mac OS X Server 10.1 - instalace, 1. část
- Některé standardní klíče a adresáře v NetInfu
- Další standardní klíče a adresáře v NetInfu
- K vašim službám 3: co nabízejí ostatní
- MacOS X Server 10.1 - instalace, druhá část.
- K vašim službám 4: vyhrazeno pro programátory
- Mac OS X a čeština
- K vašim službám 5: stále vyhrazeno pro programátory
- Tisk do souboru v OS X
- Growl - hračka nejen pro vývojáře
- PathFinder 4 - Když Finder nestačí
- RSS sem, RSS tam, co já s nimi udělám?
- Aplikace pro snadné používání služby Twitter
- Popis grafického rozhraní Mac OS X.