Kterak táhnout něco, co neexistuje? - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

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:

Soutěž

Sponzorem soutěže je:

IDIF

 

Jaký fotograf/ka získal/a cenu za nejpopulárnější příspěvek v Nikon Photo Contest?

V dnešní soutěži hrajeme o:

Seriály

Více seriálů



Informace

Kterak táhnout něco, co neexistuje?

6. března 2007, 13.00 | V poslední z kapitol věnovaných implementaci služby "drag&drop" ve vývojovém prostředí Cocoa si ukážeme speciální podporu pro možnost tažení neexistujícího souboru.

V poslední z kapitol, věnovaných implementaci služby "drag&drop" ve vývojovém prostředí Cocoa, si ukážeme speciální podporu pro možnost tažení neexistujícího souboru.

Na první pohled to vypadá poněkud nesmyslně; zamyslíme-li se však nad tím blíže, jedná se o velmi rozumnou a dosti běžnou akci: vytvoření skutečného souboru totiž je až důsledkem úspěšně dokončeného tažení a vhození. Naproti tomu, dokud tažení probíhá, žádný soubor neexistuje. Kupříkladu v našem případě můžeme implementovat takové tažení, jež uloží seznam čar do textového souboru, který můžeme "vhodit" kamkoli do Finderu nebo libovolné jiné aplikace, která podporuje korektně vhazování "would-be" souborů.

Základy

Základní princip je velmi podobný jakémukoli jinému tažení: v rámci vhodné události generované odpovídající akcí myši – nejspíše tedy mouseDown: nebo mouseDragged: – aktivujeme tažení pomocí standardní služby třídy NSView dragPromisedFilesOfTypes:fromRect:source:slideBack:event:; tentokrát není zapotřebí ani vytvářet ikonu, neboť systém automaticky doplní vhodnou ikonu podle určeného typu souboru. Pro úspěšné dokončení akce pak je třeba implementovat ještě v objektu, který řídí tažení (NSDraggingSource), metodu, jež soubory skutečně vytvoří.

Implementace

Doplníme náš projekt o odpovídající služby. Asi nejjednodušší bude, použijeme-li dalšího přepínače: v současnosti tažení s přepínačem alt vyvolá tažení objektů. Doplníme tedy implementaci tak, že přepínač command namísto toho zajistí tažení dosud neexistujícího souboru:

-(void)mouseDragged:(NSEvent*)evt {
  if (([evt modifierFlags]&NSAlternateKeyMask)
        && [lines count]) {
    NSPoint pt=[self convertPoint:[evt locationInWindow]
      fromView:nil];
    if ([evt modifierFlags]&NSCommandKeyMask)
      [self dragPromisedFilesOfTypes:
        [NSArray arrayWithObject:@"txt"]
        fromRect:NSMakeRect(pt.x-16,pt.y-16,32,32)
        source:self slideBack:YES event:evt];
    else {
      NSImage *img=...
      ... původní kód ...
    }
  } else [self setNeedsDisplay:YES];
}

Přidaný kód stačí pro inicializaci tažení i pro jeho průběh; knihovny se automaticky postarají o komunikaci s cílem a o ověření, zda cíl může přijmout soubor daného typu (resp. soubory daných typů – obecně jich samozřejmě může být více, proto je odpovídajícím argumentem pole NSArray).

Druhou metodou, již potřebujeme implementovat, je namesOfPromisedFilesDroppedAtDestination: – tu framework automaticky zavolá při úspěšném dokončení operace. V jednodušším případě, kdy vytvářených souborů není příliš mnoho a nejsou příliš velké, je nejvhodnější je přímo v metodě vytvořit a vrátit jejich jména:

-(NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)path {
  NSMutableString *ms=[NSMutableString string];
  for (id o,en=[lines objectEnumerator];o=[en nextObject];)
    [ms appendFormat:@"Line in %@\n",
      NSStringFromRect([o bounds])];
  NSString *fname=@"lines.txt";
  [ms writeToFile:[[path path]
    stringByAppendingPathComponent:fname] atomically:YES];
  return [NSArray arrayWithObject:fname];
}

Pokud bychom vytvářeli souborů více, bylo by lepší odložit vlastní zápis pomocí zprávy performSelector:withObject:afterDelay:, aby metoda namesOfPromisedFilesDroppedAtDestination: zbytečně dlouho neblokovala dokončení operace.

(Mimochodem – samozřejmě, že konkrétní seznam obdélníků omezujících čáry, který do souboru zapíšeme, není příliš praktický – v reálné aplikaci bychom do souboru spíše uložili podrobný seznam bodů, který můžeme z objektu NSBezierPath získat pomocí zprávy elementAtIndex:associatedPoints: – tento jednoduchý příklad by však bylo zbytečné tím komplikovat.)

A to je celé :)

Příjem souborů

Pokud bychom naopak chtěli "slíbené" soubory přijímat, je to ještě daleko jednodušší – pouze v rámci metody performDragOperation: pošleme objektu, řídícímu tažení, zprávu namesOfPromisedFilesDroppedAtDestination:, jejímž prostřednictvím mu sdělíme, kam má soubory uložit:

-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
  NSPasteboard *pboard=[sender draggingPasteboard];
  if ([[pboard types] containsObject:NSFilesPromisePboardType])
    [sender namesOfPromisedFilesDroppedAtDestination:TARGET];
  return YES;
}

Pokud bychom se rozhodli předaná jména souborů nějak zpracovávat, musíme si samozřejmě dát pozor na to, že ve chvíli, kdy je získáme, soubory mohou, ale ještě nemusejí být vytvořeny.

Malý dluh...

Docela nakonec se ještě na chvilku vrátíme k předminulému dílu, v něm jsme vylepšili kreslení v metodě drawRect: tak, aby při přijetí prázdného obdélníku vykreslila pouze vybrané čáry – jak to potřebujeme pro tažený obrázek.

Tehdy jsme se tázali: proč je to zcela bezpečné, dokonce i v případě, že by knihovní kód z nějakého podivného důvodu někdy naši kreslicí rutinu čirou náhodou zavolal s prázdným obdélníkem?

Samozřejmě, zkušení programátoři to již dávno vědí; jen pro jistotu a pro ty, kteří zatím s vývojovým prostředím Cocoa nemají tolik zkušeností, doplníme i odpověď: je to proto, že systémové knihovny před voláním metody drawRect: automaticky nastaví ořez na daný obdélník – v případě obdélníku prázdného by se tedy nevykreslilo vůbec nic, bez ohledu na náš kód :)

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Začínáme s  

 » Rubriky  » Software  

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: