/* ClipBookWindow.m * * Copyright (C) 2003 Free Software Foundation, Inc. * * Author: Enrico Sersale * Date: October 2003 * * This file is part of the GNUstep ClipBook application * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #include #include #include #include "ClipBookWindow.h" #include "PBViewer.h" #include "ClipBook.h" #include "Functions.h" #define WINHEIGHT 415 #define VWRHEIGHT 300 static NSString *nibName = @"ClipBookWindow.gorm"; @implementation ClipBookWindow - (void)dealloc { TEST_RELEASE (win); TEST_RELEASE (viewersBox); TEST_RELEASE (viewer); TEST_RELEASE (emptyBox); TEST_RELEASE (invalidBox); TEST_RELEASE (iconView); TEST_RELEASE (dataTypes); TEST_RELEASE (pbdir); TEST_RELEASE (pbDescrName); TEST_RELEASE (pbDescrPath); TEST_RELEASE (pbDescr); [super dealloc]; } - (id)init { self = [super init]; if(self) { if ([NSBundle loadNibNamed: nibName owner: self] == NO) { NSLog(@"ClipBookWindow Controller: failed to load %@!", nibName); } else { NSUserDefaults *defaults; NSTextField *label; NSArray *arr; defaults = [NSUserDefaults standardUserDefaults]; hideContents = [defaults boolForKey: @"hidecontents"]; if ([win setFrameUsingName: @"clipbookwindow"] == NO) { NSRect r = [win frame]; r.origin.x = 200; r.origin.x = 300; [win setFrame: r display: NO]; } else { if (hideContents == NO) { NSRect r = [win frame]; if (r.size.height != WINHEIGHT) { r.size.height = WINHEIGHT; [win setFrame: r display: NO]; } } } [win setDelegate: self]; clipbook = [ClipBook clipbook]; [win registerForDraggedTypes: [clipbook pbTypes]]; RETAIN (viewersBox); if (hideContents) { [viewersBox removeFromSuperview]; [showHideButt setImage: [NSImage imageNamed: @"common_3DArrowRight.tiff"]]; } else { [showHideButt setImage: [NSImage imageNamed: @"common_3DArrowDown.tiff"]]; } viewer = [PBViewer new]; viewerRect = [[viewersBox contentView] frame]; emptyBox = [[NSBox alloc] initWithFrame: viewerRect]; [emptyBox setBorderType: NSGrooveBorder]; [emptyBox setTitlePosition: NSNoTitle]; [emptyBox setContentViewMargins: NSMakeSize(0, 0)]; label = [[NSTextField alloc] initWithFrame: NSMakeRect(2, 133, 255, 50)]; [label setFont: [NSFont systemFontOfSize: 32]]; [label setAlignment: NSCenterTextAlignment]; [label setBackgroundColor: [NSColor windowBackgroundColor]]; [label setTextColor: [NSColor grayColor]]; [label setBezeled: NO]; [label setEditable: NO]; [label setSelectable: NO]; [label setStringValue: NSLocalizedString(@"empty", @"")]; [emptyBox setContentView: label]; RELEASE (label); invalidBox = [[NSBox alloc] initWithFrame: viewerRect]; [invalidBox setBorderType: NSGrooveBorder]; [invalidBox setTitlePosition: NSNoTitle]; [invalidBox setContentViewMargins: NSMakeSize(0, 0)]; label = [[NSTextField alloc] initWithFrame: NSMakeRect(2, 133, 255, 25)]; [label setFont: [NSFont systemFontOfSize: 18]]; [label setAlignment: NSCenterTextAlignment]; [label setBackgroundColor: [NSColor windowBackgroundColor]]; [label setTextColor: [NSColor grayColor]]; [label setBezeled: NO]; [label setEditable: NO]; [label setSelectable: NO]; [label setStringValue: NSLocalizedString(@"Invalid Contents", @"")]; [invalidBox addSubview: label]; RELEASE (label); iconView = [[PBIconView alloc] initWithFrame: [[iconBox contentView] frame]]; [iconBox setContentView: iconView]; fm = [NSFileManager defaultManager]; ASSIGN (pbdir, [clipbook pdDir]); ASSIGN (pbDescrName, @"pbDescr.plist"); ASSIGN (pbDescrPath, [pbdir stringByAppendingPathComponent: pbDescrName]); if ([fm fileExistsAtPath: pbDescrPath] == NO) { if ([[NSArray array] writeToFile: pbDescrPath atomically: YES] == NO) { NSLog(@"Can't create the main dictionary! Quitting now."); [NSApp terminate: self]; } } arr = [NSArray arrayWithContentsOfFile: pbDescrPath]; if (arr == nil) { NSLog(@"invalid array! Quitting now."); [fm movePath: pbDescrPath toPath: [pbDescrPath stringByAppendingString: @"_old"] handler: nil]; [NSApp terminate: self]; } else { pbDescr = [arr mutableCopy]; } ASSIGN (dataTypes, ([NSArray arrayWithObjects: NSStringPboardType, NSRTFPboardType, NSRTFDPboardType, NSTIFFPboardType, NSFileContentsPboardType, NSColorPboardType, @"IBViewPboardType", nil])); index = 0; isDragTarget = NO; [viewersBox setContentView: emptyBox]; [self showPbData]; } } return self; } - (void)activate { [win orderFront: nil]; } - (NSData *)readSelectionFromPasteboard:(NSPasteboard *)pboard ofType:(NSString **)pbtype { NSArray *types = [pboard types]; NSData *data; NSString *type; int i; if ((types == nil) || ([types count] == 0)) { return nil; } for (i = 0; i < [types count]; i++) { type = [types objectAtIndex: 0]; data = [pboard dataForType: type]; if (data) { *pbtype = type; return data; } } return nil; } - (void)doCut { NSDictionary *dict = [pbDescr objectAtIndex: index]; NSString *path = [dict objectForKey: @"path"]; RETAIN (path); [self doCopy]; [pbDescr removeObjectAtIndex: index]; [pbDescr writeToFile: pbDescrPath atomically: YES]; [fm removeFileAtPath: path handler: nil]; RELEASE (path); if (index > 0) { index--; } [self showPbData]; } - (void)doCopy { NSDictionary *dict = [pbDescr objectAtIndex: index]; NSString *path = [dict objectForKey: @"path"]; NSString *type = [dict objectForKey: @"type"]; NSData *data = [NSData dataWithContentsOfFile: path]; if (data) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; [pb declareTypes: [NSArray arrayWithObject: type] owner: self]; [pb setData: data forType: type]; } } - (void)doPaste { NSData *data; NSString *type; data = [self readSelectionFromPasteboard: [NSPasteboard generalPasteboard] ofType: &type]; if (data && [dataTypes containsObject: type]) { NSString *dpath = [clipbook pbFilePath]; if ([data writeToFile: dpath atomically: YES]) { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: dpath, @"path", type, @"type", nil]; if (index < [pbDescr count]) { index++; } [pbDescr insertObject: dict atIndex: index]; [pbDescr writeToFile: pbDescrPath atomically: YES]; [self showPbData]; } } } - (void)showPbData { [self checkStoredData]; if ([pbDescr count] == 0) { [viewersBox setContentView: emptyBox]; [self showPbInfo: nil]; } else { NSDictionary *dict = [pbDescr objectAtIndex: index]; NSString *path = [dict objectForKey: @"path"]; NSString *type = [dict objectForKey: @"type"]; NSData *data = [NSData dataWithContentsOfFile: path]; if (data) { id bpviewer = [viewer viewerForData: data ofType: type]; if (bpviewer) { [viewersBox setContentView: bpviewer]; [self showPbInfo: dict]; } else { [viewersBox setContentView: invalidBox]; [self showPbInfo: nil]; } } } [self updateTotalSizeLabels]; } - (NSData *)currentPBDataOfType:(NSString **)dtype { [self checkStoredData]; if ([pbDescr count]) { NSDictionary *dict = [pbDescr objectAtIndex: index]; NSString *path = [dict objectForKey: @"path"]; NSString *type = [dict objectForKey: @"type"]; NSData *data = [NSData dataWithContentsOfFile: path]; if (data) { *dtype = type; return data; } } return nil; } - (IBAction)forwardBackwardAction:(id)sender { [self showNext: ((sender == fwdButt) ? YES : NO)]; } - (void)showNext:(BOOL)fwd { if (fwd) { if (index < ([pbDescr count] -1)) { index++; [self showPbData]; } } else { if (index > 0) { index--; [self showPbData]; } } } - (void)checkStoredData { NSArray *contents = [fm directoryContentsAtPath: pbdir]; int count = [pbDescr count]; BOOL found = NO; int i, j; for (i = count -1; i >= 0; i--) { NSDictionary *dict = [pbDescr objectAtIndex: i]; NSString *dataPath = [dict objectForKey: @"path"]; if ([fm fileExistsAtPath: dataPath] == NO) { [pbDescr removeObjectAtIndex: i]; found = YES; } } if (found) { [pbDescr writeToFile: pbDescrPath atomically: YES]; } for (i = 0; i < [contents count]; i++) { NSString *fname = [contents objectAtIndex: i]; NSString *fpath = [pbdir stringByAppendingPathComponent: fname]; found = ! [pbDescr count]; for (j = 0; j < [pbDescr count]; j++) { NSDictionary *dict = [pbDescr objectAtIndex: j]; NSString *dataPath = [dict objectForKey: @"path"]; if ([dataPath isEqual: fpath] || [fpath isEqual: pbDescrPath]) { found = YES; break; } } if (found == NO) { [fm removeFileAtPath: fpath handler: nil]; } } index = (index > ([pbDescr count] -1)) ? ([pbDescr count] -1) : index; index = (index < 0) ? 0 : index; } - (void)showPbInfo:(NSDictionary *)info { if (info) { NSString *type = [info objectForKey: @"type"]; NSString *path = [info objectForKey: @"path"]; NSDictionary *attributes = [fm fileAttributesAtPath: path traverseLink: NO]; unsigned long size = [[attributes objectForKey: NSFileSize] longValue]; NSString *str; str = NSLocalizedString(@"index: ", @""); str = [str stringByAppendingFormat: @"%i", index]; [pbIndexField setStringValue: str]; str = NSLocalizedString(@"size: ", @""); str = [str stringByAppendingString: fileSizeDescription(size)]; [pbSizeField setStringValue: str]; [pbNameField setStringValue: type]; if ([type isEqual: NSStringPboardType]) { [iconView setImage: [NSImage imageNamed: @"stringPboard.tiff"]]; } else if ([type isEqual: NSRTFPboardType]) { [iconView setImage: [NSImage imageNamed: @"rtfPboard.tiff"]]; } else if ([type isEqual: NSRTFDPboardType]) { [iconView setImage: [NSImage imageNamed: @"rtfdPboard.tiff"]]; } else if ([type isEqual: NSTIFFPboardType]) { [iconView setImage: [NSImage imageNamed: @"tiffPboard.tiff"]]; } else if ([type isEqual: NSFileContentsPboardType]) { [iconView setImage: [NSImage imageNamed: @"filecontsPboard.tiff"]]; } else if ([type isEqual: NSColorPboardType]) { [iconView setImage: [NSImage imageNamed: @"colorPboard.tiff"]]; } else if ([type isEqual: @"IBViewPboardType"]) { [iconView setImage: [NSImage imageNamed: @"gormPboard.tiff"]]; } else { [iconView setImage: [NSImage imageNamed: @"Pboard.tiff"]]; } } else { [pbIndexField setStringValue: @""]; [pbNameField setStringValue: @""]; [pbSizeField setStringValue: @""]; [iconView setImage: [NSImage imageNamed: @"Pboard.tiff"]]; } } - (void)updateTotalSizeLabels { unsigned long size = 0; NSString *str; int i; for (i = 0; i < [pbDescr count]; i++) { NSDictionary *dict = [pbDescr objectAtIndex: i]; NSString *path = [dict objectForKey: @"path"]; NSDictionary *attributes = [fm fileAttributesAtPath: path traverseLink: NO]; NSNumber *sznum = [attributes objectForKey: NSFileSize]; size += [sznum longValue]; } str = fileSizeDescription(size); str = [str stringByAppendingString: NSLocalizedString(@" used", @"")]; [totalSizeField setStringValue: str]; str = [NSString stringWithFormat: @"%i %@", [pbDescr count], NSLocalizedString(@" elements", @"")]; [elementsField setStringValue: str]; } - (IBAction)showHideContents:(id)sender { NSRect r = [win frame]; if (hideContents) { r.size.height += VWRHEIGHT; [win setFrame: r display: NO]; [[win contentView] addSubview: viewersBox]; [showHideButt setImage: [NSImage imageNamed: @"common_3DArrowDown.tiff"]]; hideContents = NO; } else { r.size.height -= VWRHEIGHT; [viewersBox removeFromSuperview]; [win setFrame: r display: NO]; [showHideButt setImage: [NSImage imageNamed: @"common_3DArrowRight.tiff"]]; hideContents = YES; } } - (void)updateDefaults { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setBool: hideContents forKey: @"hidecontents"]; [defaults synchronize]; [win saveFrameUsingName: @"clipbookwindow"]; } - (id)myWin { return win; } - (BOOL)windowShouldClose:(id)sender { [self updateDefaults]; return YES; } @end @implementation ClipBookWindow (DraggingDestination) - (NSDragOperation)draggingEntered:(id )sender { NSPasteboard *pb = [sender draggingPasteboard]; NSArray *types = [pb types]; if (([types indexOfObject: NSStringPboardType] != NSNotFound) || ([types indexOfObject: NSRTFPboardType] != NSNotFound) || ([types indexOfObject: NSRTFDPboardType] != NSNotFound) || ([types indexOfObject: NSTIFFPboardType] != NSNotFound) || ([types indexOfObject: NSFileContentsPboardType] != NSNotFound) || ([types indexOfObject: NSColorPboardType] != NSNotFound) || ([types indexOfObject: @"IBViewPboardType"] != NSNotFound)) { isDragTarget = YES; return NSDragOperationCopy; } isDragTarget = NO; return NSDragOperationNone; } - (NSDragOperation)draggingUpdated:(id )sender { if (isDragTarget) { return NSDragOperationCopy; } return NSDragOperationNone; } - (void)draggingExited:(id )sender { isDragTarget = NO; } - (BOOL)prepareForDragOperation:(id )sender { return isDragTarget; } - (BOOL)performDragOperation:(id )sender { return YES; } - (void)concludeDragOperation:(id )sender { NSPasteboard *pb = [sender draggingPasteboard]; NSData *data; NSString *type; isDragTarget = NO; data = [self readSelectionFromPasteboard: pb ofType: &type]; if (data) { NSString *dpath = [clipbook pbFilePath]; if ([data writeToFile: dpath atomically: YES]) { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: dpath, @"path", type, @"type", nil]; if (index < [pbDescr count]) { index++; } [pbDescr insertObject: dict atIndex: index]; [pbDescr writeToFile: pbDescrPath atomically: YES]; [self showPbData]; } } } @end @implementation PBIconView - (id)initWithFrame:(NSRect)frameRect { self = [super initWithFrame: frameRect]; [self setEditable: NO]; [self setImageFrameStyle: NSImageFrameNone]; [self setImageAlignment: NSImageAlignCenter]; dragdelay = 0; return self; } - (void)mouseDown:(NSEvent *)theEvent { if ([theEvent clickCount] == 1) { NSEvent *nextEvent; BOOL startdnd = NO; while (1) { nextEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask]; if ([nextEvent type] == NSLeftMouseUp) { break; } else if ([nextEvent type] == NSLeftMouseDragged) { if(dragdelay < 5) { dragdelay++; } else { startdnd = YES; break; } } } if (startdnd == YES) { [self startExternalDragOnEvent: nextEvent]; } } } @end @implementation PBIconView (DraggingSource) - (void)startExternalDragOnEvent:(NSEvent *)event { NSPasteboard *pb = [NSPasteboard pasteboardWithName: NSDragPboard]; NSPoint dragPoint; if ([self declareAndSetShapeOnPasteboard: pb]) { ICONCENTER (self, [self image], dragPoint); [self dragImage: [self image] at: dragPoint offset: NSZeroSize event: event pasteboard: pb source: self slideBack: NO]; } } - (BOOL)declareAndSetShapeOnPasteboard:(NSPasteboard *)pb { NSData *data; NSString *type; data = [(ClipBookWindow *)[[self window] delegate] currentPBDataOfType: &type]; if (data) { [pb declareTypes: [NSArray arrayWithObject: type] owner: nil]; [pb setData: data forType: type]; return YES; } return NO; } - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint deposited:(BOOL)flag { dragdelay = 0; } - (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag { return NSDragOperationCopy; } @end