├── AppController.h ├── AppController.m ├── CODEOWNERS ├── ChangeLog ├── CodeEditor.h ├── CodeEditor.m ├── ColorElement.h ├── ColorElement.m ├── ControlElement.h ├── ControlElement.m ├── GNUmakefile ├── GNUmakefile.postamble ├── GNUmakefile.preamble ├── ImageElement.h ├── ImageElement.m ├── MenuItemElement.h ├── MenuItemElement.m ├── MenusElement.h ├── MenusElement.m ├── MiscElement.h ├── MiscElement.m ├── PreviewElement.h ├── PreviewElement.m ├── README ├── Resources ├── CodeEditor.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── CodeInfo.plist ├── ColorElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── CommonMethods.txt ├── ControlElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── ImageAdd.png ├── ImageElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── IncludeHeaders.txt ├── MakeAdditions.txt ├── MenusElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── MiscElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── PreviewElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── Thematic.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── Thematic.png ├── ThematicHelp.rtf ├── ThemeDocument.gorm │ ├── MenusPalette.tiff │ ├── data.classes │ ├── data.info │ ├── objects.gorm │ ├── themeColors.tiff │ ├── themeImages.tiff │ ├── themeMenu.tiff │ ├── themeMisc.tiff │ └── themeWindow.tiff ├── ThemeInspector.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── VariableDeclarations.txt ├── WindowsElement.gorm │ ├── data.classes │ ├── data.info │ └── objects.gorm ├── drawBorderAndBackgroundForMenuItemCell_withFrame_inView_state_isHorizontal_.txt └── drawButton_in_view_style_state_.txt ├── Thematic.pcproj └── PC.project ├── Thematic.png ├── ThematicInfo.plist ├── ThemeDocument.h ├── ThemeDocument.m ├── ThemeElement.h ├── ThemeElement.m ├── TilesBox.h ├── TilesBox.m ├── WindowsElement.h ├── WindowsElement.m └── main.m /AppController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Project: Thematic 3 | 4 | Copyright (C) 2006-2020 Free Software Foundation 5 | 6 | Authors: Richard Frith-MacDonald 7 | Riccardo Mottola 8 | 9 | Created: 2006-09-18 14:00:14 +0100 by richard 10 | 11 | Application Controller 12 | 13 | This application is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public 15 | License as published by the Free Software Foundation; either 16 | version 2 of the License, or (at your option) any later version. 17 | 18 | This application is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | Library General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public 24 | License along with this library; if not, write to the Free Software 25 | Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 26 | */ 27 | 28 | #import 29 | 30 | 31 | @class ThemeDocument; 32 | 33 | @interface AppController : NSObject 34 | { 35 | id inspector; 36 | NSMutableArray *documents; 37 | ThemeDocument *currentDocument; // Not retained 38 | NSDictionary *codeInfo; 39 | NSString *lastPathUsed; 40 | } 41 | 42 | + (void) initialize; 43 | + (AppController*) sharedController; 44 | 45 | - (id) init; 46 | - (void) dealloc; 47 | 48 | - (void) awakeFromNib; 49 | - (NSDictionary*) codeInfo; 50 | 51 | - (void) applicationDidFinishLaunching: (NSNotification *)aNotif; 52 | - (void) applicationWillTerminate: (NSNotification *)aNotif; 53 | - (BOOL) application: (NSApplication *)application 54 | openFile: (NSString *)fileName; 55 | 56 | - (NSArray*) documents; 57 | - (NSWindow*) inspector; 58 | - (void) newDocument: (id)sender; 59 | - (void) openDocument: (id)sender; 60 | - (void) openInspector: (id)sender; 61 | /** Remove the sender from the array of documents */ 62 | - (void) removeDocument: (ThemeDocument*)sender; 63 | - (void) saveAllDocuments: (id)sender; 64 | /** Select the sender as the current document */ 65 | - (void) selectDocument: (ThemeDocument*)sender; 66 | /** Return the currently selected document or nil if noe is selected */ 67 | - (ThemeDocument*) selectedDocument; 68 | - (void) showPrefPanel: (id)sender; 69 | 70 | @end 71 | 72 | extern AppController *thematicController; 73 | -------------------------------------------------------------------------------- /AppController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Project: Thematic 3 | 4 | Copyright (C) 2006-2020 Free Software Foundation 5 | 6 | Authors: Richard Frith-MacDonald 7 | Riccardo Mottola 8 | 9 | Created: 2006-09-18 14:00:14 +0100 by richard 10 | 11 | Application Controller 12 | 13 | This application is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public 15 | License as published by the Free Software Foundation; either 16 | version 2 of the License, or (at your option) any later version. 17 | 18 | This application is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | Library General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public 24 | License along with this library; if not, write to the Free Software 25 | Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 26 | */ 27 | 28 | #import "AppController.h" 29 | #import "ThemeDocument.h" 30 | 31 | @implementation AppController 32 | 33 | AppController *thematicController = nil; 34 | 35 | + (void) initialize 36 | { 37 | NSMutableDictionary *defaults = [NSMutableDictionary dictionary]; 38 | 39 | /* 40 | * Register your app's defaults here by adding objects to the 41 | * dictionary, eg 42 | * 43 | * [defaults setObject: anObject forKey: keyForThatObject]; 44 | * 45 | */ 46 | 47 | [[NSUserDefaults standardUserDefaults] registerDefaults: defaults]; 48 | [[NSUserDefaults standardUserDefaults] synchronize]; 49 | 50 | /* Support clear button background. 51 | */ 52 | [NSColor setIgnoresAlpha: NO]; 53 | } 54 | 55 | + (AppController*) sharedController 56 | { 57 | if (thematicController == nil) 58 | { 59 | [self new]; 60 | } 61 | return thematicController; 62 | } 63 | 64 | - (id) init 65 | { 66 | if (thematicController == nil) 67 | { 68 | if ((self = [super init])) 69 | { 70 | thematicController = self; 71 | documents = [NSMutableArray new]; 72 | /* Load the property list which defines the API for the code 73 | * fragments for each control. For each control name, this 74 | * dictionary should contain another dictionary mapping method 75 | * names to their help text. 76 | */ 77 | codeInfo = [[NSDictionary alloc] initWithContentsOfFile: 78 | [[NSBundle mainBundle] pathForResource: @"CodeInfo" 79 | ofType: @"plist"]]; 80 | 81 | lastPathUsed = nil; 82 | } 83 | } 84 | else 85 | { 86 | RELEASE(self); 87 | self = RETAIN(thematicController); 88 | } 89 | return self; 90 | } 91 | 92 | - (void) dealloc 93 | { 94 | if (thematicController == self) 95 | { 96 | thematicController = nil; 97 | } 98 | RELEASE(currentDocument); 99 | RELEASE(documents); 100 | RELEASE(codeInfo); 101 | RELEASE(lastPathUsed); 102 | [super dealloc]; 103 | } 104 | 105 | - (void) awakeFromNib 106 | { 107 | [[NSApp mainMenu] setTitle: @"Thematic"]; 108 | [NSApp setDelegate: self]; 109 | } 110 | 111 | - (void) applicationDidFinishLaunching: (NSNotification *)aNotif 112 | { 113 | } 114 | 115 | - (NSApplicationTerminateReply) applicationShouldTerminate: (id)sender 116 | { 117 | return NSTerminateNow; 118 | } 119 | 120 | - (void) applicationWillTerminate: (NSNotification *)aNotif 121 | { 122 | } 123 | 124 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender 125 | { 126 | // We don't want to terminate immediately and we force this to NO 127 | // GUI tries to be smart and say YES if a NSWindows95InterfaceStyle is loaded 128 | // But We only want to edit such a theme, othwise during a theme load 129 | // it may crash 130 | return NO; 131 | } 132 | 133 | - (BOOL) application: (NSApplication *)application 134 | openFile: (NSString *)fileName 135 | { 136 | ThemeDocument *doc; 137 | unsigned i = [documents count]; 138 | 139 | /* Check to see if we already have it open. 140 | */ 141 | while (i-- > 0) 142 | { 143 | doc = [documents objectAtIndex: i]; 144 | if ([[doc path] isEqual: fileName] == YES) 145 | { 146 | /* Already open ... select it 147 | */ 148 | [self selectDocument: doc]; 149 | return YES; 150 | } 151 | } 152 | 153 | /* Not open ... open it 154 | */ 155 | doc = [[ThemeDocument alloc] initWithPath: fileName]; 156 | if (doc != nil) 157 | { 158 | [documents addObject: doc]; 159 | RELEASE(doc); 160 | [self selectDocument: doc]; 161 | } 162 | return YES; 163 | } 164 | 165 | - (NSDictionary*) codeInfo 166 | { 167 | return codeInfo; 168 | } 169 | 170 | - (NSArray*) documents 171 | { 172 | return [[documents copy] autorelease]; 173 | } 174 | 175 | - (NSWindow*) inspector 176 | { 177 | if (inspector == nil) 178 | { 179 | [NSBundle loadNibNamed: @"ThemeInspector" owner: self]; 180 | [inspector setFrameUsingName: @"Inspector"]; 181 | [inspector setFrameAutosaveName: @"Inspector"]; 182 | } 183 | return (NSWindow*)inspector; 184 | } 185 | 186 | - (void) newDocument: (id)sender 187 | { 188 | ThemeDocument *doc = [ThemeDocument new]; 189 | 190 | if (doc != nil) 191 | { 192 | [documents addObject: doc]; 193 | RELEASE(doc); 194 | [self selectDocument: doc]; 195 | } 196 | } 197 | 198 | - (void) openDocument: (id)sender 199 | { 200 | NSArray *fileTypes = [NSArray arrayWithObject: @"theme"]; 201 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 202 | int result; 203 | NSFileManager *mgr = [NSFileManager defaultManager]; 204 | BOOL isDir; 205 | NSString *base; 206 | 207 | base = [NSSearchPathForDirectoriesInDomains 208 | (NSAllLibrariesDirectory, NSUserDomainMask, YES) lastObject]; 209 | if (base != nil) 210 | { 211 | base = [base stringByAppendingPathComponent: @"Themes"]; 212 | if ([mgr fileExistsAtPath: base isDirectory: &isDir] == NO 213 | || isDir == NO) 214 | { 215 | base = nil; 216 | } 217 | } 218 | if (base == nil) 219 | { 220 | base = NSHomeDirectory(); 221 | } 222 | if (lastPathUsed == nil) 223 | lastPathUsed = [base retain]; 224 | 225 | [oPanel setAllowsMultipleSelection: NO]; 226 | [oPanel setCanChooseFiles: YES]; 227 | [oPanel setCanChooseDirectories: NO]; 228 | result = [oPanel runModalForDirectory: lastPathUsed 229 | file: nil 230 | types: fileTypes]; 231 | if (result == NSOKButton) 232 | { 233 | NSString *path = [oPanel filename]; 234 | 235 | NS_DURING 236 | { 237 | [path retain]; 238 | [self application: NSApp openFile: path]; 239 | DESTROY(lastPathUsed); 240 | lastPathUsed = [[path stringByDeletingLastPathComponent] retain]; 241 | [path release]; 242 | } 243 | NS_HANDLER 244 | { 245 | NSString *message = [localException reason]; 246 | NSRunAlertPanel(_(@"Problem parsing class"), 247 | message, 248 | nil, nil, nil); 249 | } 250 | NS_ENDHANDLER 251 | } 252 | } 253 | 254 | - (void) openInspector: (id)sender 255 | { 256 | [[self inspector] makeKeyAndOrderFront: self]; 257 | } 258 | 259 | - (void) removeDocument: (ThemeDocument*)sender 260 | { 261 | [documents removeObjectIdenticalTo: sender]; 262 | if (currentDocument == sender) 263 | { 264 | [self selectDocument: [documents lastObject]]; 265 | } 266 | } 267 | 268 | - (void) saveAllDocuments: (id)sender 269 | { 270 | NSArray *docs = AUTORELEASE([documents copy]); 271 | unsigned i = [docs count]; 272 | 273 | while (i-- > 0) 274 | { 275 | ThemeDocument *doc = [docs objectAtIndex: i]; 276 | 277 | if ([documents indexOfObjectIdenticalTo: doc] != NSNotFound) 278 | { 279 | [doc saveDocument: sender]; 280 | } 281 | } 282 | } 283 | 284 | - (void) selectDocument: (ThemeDocument*)sender 285 | { 286 | if (currentDocument != sender) 287 | { 288 | currentDocument = sender; 289 | [currentDocument activate]; 290 | } 291 | } 292 | 293 | - (ThemeDocument*) selectedDocument 294 | { 295 | return currentDocument; 296 | } 297 | 298 | - (void) showPrefPanel: (id)sender 299 | { 300 | } 301 | 302 | @end 303 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | # @global-owner1 and @global-owner2 will be requested for 4 | # review when someone opens a pull request. 5 | * @rfm 6 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2021-03-07 Gregory John Casamento 2 | 3 | * Resources/ControlElement.gorm: Correct resizing so that the elements 4 | correctly redraw themselves after a resize of the window. 5 | 6 | 2020-11-29 Riccardo Mottola 7 | 8 | * AppController.m 9 | Override applicationShouldTerminateAfterLastWindowClosed so that when switching to NSWindows95InterfaceStyle the application doesn't close. 10 | 11 | 2020-11-27 Riccardo Mottola 12 | 13 | * AppController.h 14 | * AppController.m 15 | Remember last opened directory and suggest it to the user again. 16 | 17 | 2019-07-08 Riccardo Mottola 18 | 19 | * ColorElement.m 20 | Add support for ToolTip colors. 21 | 22 | 2015-11-24 Riccardo Mottola 23 | 24 | * ThemeDocument.m (applicationImageNames) 25 | Scan for Images and su-dirs explicitely and skip over all hidden directories, instead of one big directory enumerator. 26 | 27 | * ImageElement.m (initWithView:) 28 | Set appropriate tag for each collection. 29 | 30 | 2015-11-19 Riccardo Mottola 31 | 32 | * ImageElement.m 33 | Add new images (Recycler, Multiple selection). 34 | 35 | 2014-01-12 Sebastian Reitenbach 36 | * ThemeDocument.m 37 | change return type of -draggingEntered from unsigned 38 | to NSDragOperation 39 | 40 | 2013-11-05 Eric Wasylishen 41 | 42 | * ColorElement.m: Add extra colors @"highlightedTableRowBackgroundColor" 43 | and @"highlightedTableRowTextColor". 44 | 45 | 2013-10-04 Eric Wasylishen 46 | 47 | * ColorElement.h: 48 | * ColorElement.m: Add support for setting all the "theme extra colors" 49 | currently used in gui. 50 | * Resources/ThemeInspector.gorm: Make resizable 51 | 52 | 2013-10-04 Eric Wasylishen 53 | 54 | * ColorElement.h: 55 | * ColorElement.m: 56 | * Resources/ColorElement.gorm: Rewrite ColorElement using the color list 57 | table code from GSTest, so you can see all of the colors at once, and 58 | we can easily add more in code. 59 | 60 | 2013-07-01 Riccardo Mottola 61 | 62 | * MiscElement.h 63 | * MiscElement.m 64 | * Resources/MiscElement.gorm 65 | Add license property and field. 66 | 67 | 2013-03-16 Riccardo Mottola 68 | 69 | * MenusElement.m 70 | Theme common_3DArrowRight.tiff and not NSMenuArrow, that is use the GS name. 71 | 72 | 2013-04-10 Wolfgang Lux 73 | 74 | * ThemeDocument.m (-dealloc): Reset window delegate to prevent 75 | crash when the document is closed. 76 | 77 | * Resources/ThemeDocument.gorm: Set release when closed attribute 78 | to fix space leak. 79 | 80 | 2013-03-08 Riccardo Mottola 81 | 82 | * ImageElement.m: 83 | Allow theming of unknown files. 84 | 85 | 2010-12-14 Riccardo Mottola 86 | 87 | * ImageElement.m: 88 | added new themable images for Destkop and Music folder 89 | 90 | 2010-12-09 Riccardo Mottola 91 | 92 | * ImageElement.m: 93 | added new themable images for folders 94 | 95 | 2010-08-06 German Arias 96 | 97 | * ControlElement.m: 98 | * Resources/CodeInfo.plist: 99 | Added Disabled state to buttons. 100 | 101 | 2010-06-18 Riccardo Mottola 102 | 103 | * PreviewElement.m 104 | * CodeEditor.m 105 | Warning fixes 106 | 107 | 2010-06-08 German Arias 108 | 109 | * ColorElement.m: 110 | Changes to set the theme color at begining. 111 | 112 | 2010-06-08 German Arias 113 | 114 | * MenusElement.m 115 | * Resources/MenusElement.gorm/objects.gorm 116 | Changes to set Black and White when extra colors GSMenuBar 117 | and GSMenuBarTitle are not specified. 118 | 119 | 2010-06-08 German Arias 120 | 121 | * MenusElement.h 122 | * MenusElement.m 123 | * Resources/MenusElement.gorm/data.info 124 | * Resources/MenusElement.gorm/data.classes 125 | * Resources/MenusElement.gorm/objects.gorm 126 | Changes to allow set extra colors GSMenuBar and GSMenuBarTitle. 127 | 128 | 2009-10-08 Riccardo Mottola 129 | * ImageElement.m: 130 | Added Root PC to images 131 | 132 | 2009-08-31 Richard Frith-Macdonald 133 | 134 | Set title of inspector window to reflect what is being inspected. 135 | 136 | 2009-08-28 17:37-EDT Gregory John Casamento 137 | 138 | * ImageElement.m: Added change to support new image element 139 | for horizontal scroller knob. 140 | 141 | 2009-08-28 Richard Frith-Macdonald 142 | 143 | * ImageElement.m: 144 | Allow deletion of images to restore default GNUstep images. 145 | 146 | 2009-08-26 Richard Frith-Macdonald 147 | 148 | * ControlElement.m: 149 | Improve handling of cases where we have no info in the plist. 150 | Try to fix initialisation of scroller element info panel. 151 | 152 | 2009-08-26 Riccardo Mottola 153 | * ImageElement.m: 154 | Added Switch button images 155 | 156 | 2009-08-24 17:05-BST Richard Frith-Macdonald 157 | 158 | * ControlElement.m: 159 | * ThemeDocument.m: 160 | * ThemeElement.m: 161 | Show alert panel if we have an unknown control to inspect. 162 | Display name of class being inspected in window title. 163 | Cleanup a bit. 164 | 165 | 2009-08-24 14:55-BST Richard Frith-Macdonald 166 | 167 | * Resources/CommonMethods.txt: 168 | * Resources/VariableDeclarations.txt: 169 | * Resources/IncludeHeaders.txt: 170 | * ControlElement.m: 171 | * ThemeDocument.m: 172 | * CodeEditor.m: 173 | Document a little in comments in templates. 174 | Change code editor to put methods in separate categories (at some 175 | point we should use separate files for faster compilation when only 176 | one method has changed). 177 | Fix coordinate mapping to find views on main document windows. 178 | Add code to detect which part of a scroller is hit, and alter the 179 | inspector to select it. 180 | 181 | 2009-08-22 17:44-EDT Gregory John Casamento 182 | 183 | * Resources/ThemeDocument.gorm: Change the window so that it's 184 | not resizable. Also add some more widgets to the document. 185 | 186 | -------------------------------------------------------------------------------- /CodeEditor.h: -------------------------------------------------------------------------------- 1 | /* CodeEditor.h 2 | * 3 | * Copyright (C) 2008 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | #include 25 | 26 | @class ThemeDocument; 27 | 28 | @interface CodeEditor : NSObject 29 | { 30 | id textView; 31 | id panel; 32 | NSString *text; 33 | NSString *control; 34 | NSString *method; 35 | } 36 | + (CodeEditor*) codeEditor; 37 | - (void) codeBuildFor: (ThemeDocument*)document method: (NSString*)method; 38 | - (void) codeDone: (id)sender; 39 | - (void) codeRevert: (id)sender; 40 | - (void) codeCancel: (id)sender; 41 | - (void) editText: (NSString*)t control: (NSString*)c method: (NSString*)m; 42 | - (void) endEdit; 43 | - (NSTextView*) textView; 44 | @end 45 | -------------------------------------------------------------------------------- /CodeEditor.m: -------------------------------------------------------------------------------- 1 | /* CodeEditor.h 2 | * 3 | * Copyright (C) 2008-2010 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import "AppController.h" 27 | #import "ThemeDocument.h" 28 | #import "CodeEditor.h" 29 | 30 | @implementation CodeEditor 31 | 32 | static CodeEditor *instance = nil; 33 | 34 | + (CodeEditor*) codeEditor 35 | { 36 | if (instance == nil) 37 | { 38 | [self new]; 39 | } 40 | return instance; 41 | } 42 | 43 | 44 | - (void) codeBuildFor: (ThemeDocument*)document method: (NSString*)singleMethod 45 | { 46 | NSFileManager *mgr = [NSFileManager defaultManager]; 47 | AppController *app = [AppController sharedController]; 48 | NSProcessInfo *pi = [NSProcessInfo processInfo]; 49 | NSDictionary *codeInfo; 50 | NSMutableSet *methods; 51 | NSString *methodName; 52 | NSEnumerator *enumerator; 53 | NSDictionary *generic; 54 | NSString *path; 55 | NSString *fullName; 56 | NSMutableString *codeText; 57 | NSMutableString *makeText; 58 | NSString *launchPath; 59 | NSTask *task; 60 | NSString *string; 61 | NSString *logFile; 62 | NSFileHandle *logHandle; 63 | int status; 64 | 65 | string = [[pi environment] objectForKey: @"GNUSTEP_MAKEFILES"]; 66 | if (string == nil && [NSTask launchPathForTool: @"gnustep-install"] == nil) 67 | { 68 | NSRunAlertPanel(_(@"Problem building theme"), 69 | _(@"Can't locate gnustep-make (no GNUSTEP_MAKEFILES in environment)"), 70 | nil, nil, nil, nil); 71 | [document setBinaryBundle: nil]; 72 | } 73 | 74 | fullName = [NSString stringWithFormat: @"%@_%@", 75 | [[document name] stringByDeletingPathExtension], 76 | [[document versionIncrementMajor: NO incrementMinor: YES] 77 | stringByReplacingString: @"." withString: @"_"]]; 78 | 79 | codeInfo = [app codeInfo]; 80 | /* The items in the generic dictionary are handled specially rather 81 | * than being treated as methods. 82 | */ 83 | generic = [codeInfo objectForKey: @"Generic"]; 84 | if (singleMethod != nil && [generic objectForKey: singleMethod] != nil) 85 | { 86 | singleMethod = nil; 87 | } 88 | 89 | makeText = [NSMutableString string]; 90 | [makeText appendString: @"ifeq ($(GNUSTEP_MAKEFILES),)\n"]; 91 | [makeText appendString: @" GNUSTEP_MAKEFILES := $(shell gnustep-config "]; 92 | [makeText appendString: @" --variable=GNUSTEP_MAKEFILES 2>/dev/null)\n"]; 93 | [makeText appendString: @"endif\n"]; 94 | [makeText appendString: @"include $(GNUSTEP_MAKEFILES)/common.make\n"]; 95 | [makeText appendString: @"BUNDLE_NAME=Theme\n"]; 96 | string = [document codeForKey: @"MakeAdditions" since: 0]; 97 | if ([string length] > 0) 98 | { 99 | [makeText appendString: @"\n"]; 100 | [makeText appendString: string]; 101 | [makeText appendString: @"\n"]; 102 | } 103 | [makeText appendString: @"Theme_OBJC_FILES=Theme.m\n"]; 104 | [makeText appendFormat: @"Theme_PRINCIPAL_CLASS=%@\n", fullName]; 105 | [makeText appendString: @"include $(GNUSTEP_MAKEFILES)/bundle.make\n"]; 106 | 107 | codeText = [NSMutableString string]; 108 | [codeText appendString: @"#import \n"]; 109 | [codeText appendString: @"#import \n"]; 110 | string = [document codeForKey: @"IncludeHeaders" since: 0]; 111 | if ([string length] > 0) 112 | { 113 | [codeText appendString: @"\n"]; 114 | [codeText appendString: string]; 115 | [codeText appendString: @"\n"]; 116 | } 117 | 118 | /* Write out the main theme interface document. 119 | */ 120 | [codeText appendFormat: @"@interface %@ : GSTheme\n", fullName]; 121 | string = [document codeForKey: @"VariableDeclarations" since: 0]; 122 | if ([string length] > 0) 123 | { 124 | [codeText appendString: @"\n"]; 125 | [codeText appendString: string]; 126 | [codeText appendString: @"\n"]; 127 | } 128 | [codeText appendString: @"@end\n"]; 129 | 130 | /* Write out the common code. 131 | */ 132 | [codeText appendFormat: @"@implementation %@\n", fullName]; 133 | string = [document codeForKey: @"CommonMethods" since: 0]; 134 | if ([string length] > 0) 135 | { 136 | [codeText appendString: @"\n"]; 137 | [codeText appendString: string]; 138 | [codeText appendString: @"\n"]; 139 | } 140 | [codeText appendString: @"@end\n"]; 141 | 142 | methods = [[NSMutableSet alloc] autorelease]; 143 | if (singleMethod == nil) 144 | { 145 | NSDictionary *controlInfo; 146 | 147 | /* Build with all methods. 148 | */ 149 | enumerator = [codeInfo objectEnumerator]; 150 | while ((controlInfo = [enumerator nextObject]) != nil) 151 | { 152 | if (controlInfo != generic) 153 | { 154 | [methods addObjectsFromArray: [controlInfo allKeys]]; 155 | } 156 | } 157 | } 158 | else 159 | { 160 | /* Build a single method. 161 | */ 162 | [methods addObject: singleMethod]; 163 | } 164 | 165 | enumerator = [methods objectEnumerator]; 166 | while ((methodName = [enumerator nextObject]) != nil) 167 | { 168 | NSString *code = [document codeForKey: methodName since: 0]; 169 | 170 | if (code != nil) 171 | { 172 | [codeText appendFormat: @"@implementation %@ (%@)\n", fullName, 173 | [methodName stringByReplacingString: @":" withString: @"_"]]; 174 | [codeText appendString: @"\n"]; 175 | [codeText appendString: code]; 176 | [codeText appendString: @"@end\n"]; 177 | } 178 | } 179 | 180 | path = [document buildDirectory]; 181 | 182 | [makeText writeToFile: [path stringByAppendingPathComponent: @"GNUmakefile"] 183 | atomically: NO]; 184 | [codeText writeToFile: [path stringByAppendingPathComponent: @"Theme.m"] 185 | atomically: NO]; 186 | logFile = [path stringByAppendingPathComponent: @"make.log"]; 187 | [mgr createFileAtPath: logFile contents: nil attributes: nil]; 188 | logHandle = [NSFileHandle fileHandleForWritingAtPath: logFile]; 189 | 190 | [mgr createDirectoryAtPath: path attributes: nil]; 191 | launchPath = [NSTask launchPathForTool: @"gmake"]; 192 | if (launchPath == nil) 193 | { 194 | launchPath = [NSTask launchPathForTool: @"gmake"]; 195 | if (launchPath == nil) 196 | { 197 | [mgr removeFileAtPath: path handler: nil]; 198 | NSRunAlertPanel(_(@"Problem building theme"), 199 | _(@"Unable to locate 'make' program"), 200 | nil, nil, nil, nil); 201 | [document setBinaryBundle: nil]; 202 | } 203 | } 204 | task = [NSTask new]; 205 | [task setLaunchPath: launchPath]; 206 | [task setCurrentDirectoryPath: path]; 207 | [task setStandardError: logHandle]; 208 | [task setStandardOutput: logHandle]; 209 | [task launch]; 210 | while ([task isRunning]) 211 | { 212 | CREATE_AUTORELEASE_POOL(arp); 213 | [[NSRunLoop currentRunLoop] runUntilDate: 214 | [NSDate dateWithTimeIntervalSinceNow: 0.1]]; 215 | RELEASE(arp); 216 | } 217 | status = [task terminationStatus]; 218 | [task release]; 219 | if (status == 0) 220 | { 221 | [document setBinaryBundle: 222 | [path stringByAppendingPathComponent: @"Theme.bundle"]]; 223 | } 224 | else 225 | { 226 | NSString *output = [NSString stringWithContentsOfFile: logFile]; 227 | 228 | NSRunAlertPanel(_(@"Problem building theme"), 229 | _(@"Build operation failed: %@"), 230 | nil, nil, nil, output); 231 | [document setBinaryBundle: nil]; 232 | } 233 | } 234 | 235 | - (void) codeDone: (id)sender 236 | { 237 | NSDictionary *userInfo; 238 | 239 | userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 240 | [textView text], @"Text", 241 | control, @"Control", 242 | method, @"Method", 243 | nil]; 244 | [[NSNotificationCenter defaultCenter] 245 | postNotificationName: @"CodeEditDone" 246 | object: self 247 | userInfo: userInfo]; 248 | 249 | [self endEdit]; 250 | } 251 | 252 | 253 | - (void) codeRevert: (id)sender 254 | { 255 | [textView setText: text]; 256 | } 257 | 258 | 259 | - (void) codeCancel: (id)sender 260 | { 261 | [self endEdit]; 262 | } 263 | 264 | 265 | - (void) dealloc 266 | { 267 | [text release]; 268 | [control release]; 269 | [method release]; 270 | [super dealloc]; 271 | } 272 | 273 | 274 | - (void) editText: (NSString*)t control: (NSString*)c method: (NSString*)m 275 | { 276 | ASSIGNCOPY(text, t); 277 | ASSIGNCOPY(control, c); 278 | ASSIGNCOPY(method, m); 279 | [[self textView] setText: text]; 280 | [panel setTitle: m]; 281 | [panel makeKeyAndOrderFront: self]; 282 | } 283 | 284 | 285 | - (void) endEdit 286 | { 287 | [panel orderOut: self]; 288 | [textView setText: @""]; 289 | DESTROY(text); 290 | DESTROY(control); 291 | DESTROY(method); 292 | } 293 | 294 | 295 | - (id) init 296 | { 297 | if (instance == nil) 298 | { 299 | instance = self; 300 | } 301 | else if (instance != self) 302 | { 303 | [self release]; 304 | self = instance; 305 | } 306 | return self; 307 | } 308 | 309 | 310 | - (NSTextView*) textView 311 | { 312 | if (textView == nil) 313 | { 314 | [NSBundle loadNibNamed: @"CodeEditor" owner: self]; 315 | } 316 | return (NSTextView*)textView; 317 | } 318 | 319 | @end 320 | -------------------------------------------------------------------------------- /ColorElement.h: -------------------------------------------------------------------------------- 1 | /* ColorElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import "ThemeElement.h" 26 | 27 | @interface ColorElement : ThemeElement 28 | { 29 | BOOL ignoreSelectAt; 30 | } 31 | 32 | /** Handle color setting from color well in inspector 33 | */ 34 | - (void) takeColorFrom: (id)sender; 35 | 36 | - (NSColor *) colorForName: (NSString *)aName 37 | isSystem: (BOOL)system 38 | state: (GSThemeControlState)state; 39 | - (void) setColor: (NSColor *)aColor 40 | forName: (NSString *)aName 41 | isSystem: (BOOL)system 42 | state: (GSThemeControlState)state; 43 | 44 | - (NSInteger) tagForName: (NSString *)aName 45 | isSystem: (BOOL)system 46 | state: (GSThemeControlState)state; 47 | - (NSString *) nameForTag: (NSInteger)tag; 48 | - (BOOL) tagIsSystem: (NSInteger)tag; 49 | - (GSThemeControlState) themeControlStateForTag: (NSInteger)tag; 50 | 51 | @end 52 | 53 | -------------------------------------------------------------------------------- /ColorElement.m: -------------------------------------------------------------------------------- 1 | /* ColorElement.m 2 | * 3 | * Copyright (C) 2006-2019 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import "AppController.h" 31 | #import "ThemeDocument.h" 32 | #import "ColorElement.h" 33 | 34 | @implementation ColorElement 35 | 36 | /** 37 | * Basic set of 33 system colors; the default values are 38 | * defined inside NSColor in gnustep-gui. 39 | */ 40 | static NSArray *systemColorNames; 41 | 42 | /** 43 | * Extra colors use by GSTheme. Each of these names 44 | * is associated with a normal color, a highlighted color, 45 | * and a selected color. 46 | */ 47 | static NSArray *extraColorNames; 48 | 49 | + (void) initialize 50 | { 51 | if (self == [ColorElement class]) 52 | { 53 | // This list should not be changed 54 | systemColorNames = [[NSArray alloc] initWithObjects: 55 | @"alternateRowBackgroundColor", 56 | @"alternateSelectedControlColor", 57 | @"alternateSelectedControlTextColor", 58 | @"controlBackgroundColor", 59 | @"controlColor", 60 | @"controlDarkShadowColor", 61 | @"controlHighlightColor", 62 | @"controlLightHighlightColor", 63 | @"controlShadowColor", 64 | @"controlTextColor", 65 | @"disabledControlTextColor", 66 | @"gridColor", 67 | @"headerColor", 68 | @"headerTextColor", 69 | @"highlightColor", 70 | @"nameboardFocusIndicatorColor", 71 | @"knobColor", 72 | @"rowBackgroundColor", 73 | @"scrollBarColor", 74 | @"secondarySelectedControlColor", 75 | @"selectedControlColor", 76 | @"selectedControlTextColor", 77 | @"selectedKnobColor", 78 | @"selectedMenuItemColor", 79 | @"selectedMenuItemTextColor", 80 | @"selectedTextBackgroundColor", 81 | @"selectedTextColor", 82 | @"shadowColor", 83 | @"textBackgroundColor", 84 | @"textColor", 85 | @"toolTipColor", 86 | @"toolTipTextColor", 87 | @"windowBackgroundColor", 88 | @"windowFrameColor", 89 | @"windowFrameTextColor", 90 | nil]; 91 | 92 | /* Feel free to add extra colors here as they are added 93 | * in GSThemeDrawing.m 94 | */ 95 | extraColorNames = [[NSArray alloc] initWithObjects: 96 | @"toolbarBackgroundColor", 97 | @"toolbarBorderColor", 98 | @"menuBackgroundColor", 99 | @"menuItemBackgroundColor", 100 | @"menuBorderColor", 101 | @"menuBarBackgroundColor", 102 | @"menuBarBorderColor", 103 | @"menuSeparatorColor", 104 | @"GSMenuBar", 105 | @"GSMenuBarTitle", 106 | @"tableHeaderTextColor", 107 | @"keyWindowFrameTextColor", 108 | @"normalWindowFrameTextColor", 109 | @"mainWindowFrameTextColor", 110 | @"windowBorderColor", 111 | @"browserHeaderTextColor", 112 | @"NSScrollView", 113 | @"highlightedTableRowBackgroundColor", 114 | @"highlightedTableRowTextColor", 115 | nil]; 116 | } 117 | } 118 | 119 | - (NSTextField *) makeTextFieldWithLabel: (NSString *)aLabel 120 | { 121 | NSTextField *text = [[NSTextField alloc] init]; 122 | 123 | [text setEditable: NO]; 124 | [text setBezeled: NO]; 125 | [text setDrawsBackground: NO]; 126 | [text setStringValue: aLabel]; 127 | [text sizeToFit]; 128 | [text setAutoresizingMask: (NSViewMinYMargin | NSViewMaxYMargin)]; 129 | return AUTORELEASE(text); 130 | } 131 | 132 | - (NSTextField *) makeBoldLabel: (NSString *)aLabel 133 | { 134 | NSTextField *text = [self makeTextFieldWithLabel: aLabel]; 135 | 136 | [text setFont: [NSFont boldSystemFontOfSize: 12.0]]; 137 | [text setSelectable: NO]; 138 | [text sizeToFit]; 139 | return text; 140 | } 141 | 142 | - (NSColorWell *) makeColorWellWithTag: (NSInteger)aTag 143 | color: (NSColor *)aColor 144 | { 145 | NSColorWell *color; 146 | 147 | color = [[NSColorWell alloc] initWithFrame: NSMakeRect (0, 0, 50, 30)]; 148 | [color setTag: aTag]; 149 | [color setTarget: self]; 150 | [color setAction: @selector(takeColorFrom:)]; 151 | [color setColor: aColor]; 152 | [color setAutoresizingMask: NSViewMinXMargin]; 153 | return AUTORELEASE(color); 154 | } 155 | 156 | - (NSColorWell *) makeColorWellWithName: (NSString *)aName 157 | isSystem: (BOOL)system 158 | state: (GSThemeControlState)state 159 | { 160 | int tag; 161 | NSColor *color; 162 | 163 | tag = [self tagForName: aName isSystem: system state: state]; 164 | color = [self colorForName: aName isSystem: system state: state]; 165 | return [self makeColorWellWithTag: tag color: color]; 166 | } 167 | 168 | - (GSVbox *) makeSystemColorListVbox 169 | { 170 | GSVbox *vbox = [[GSVbox new] autorelease]; 171 | int i; 172 | int count = [systemColorNames count]; 173 | 174 | [vbox setDefaultMinYMargin: 2]; 175 | [vbox setBorder: 2]; 176 | 177 | for (i = 0; i < count; i++) 178 | { 179 | GSHbox *hbox = [[[GSHbox alloc] init] autorelease]; 180 | NSString *name = [systemColorNames objectAtIndex: i]; 181 | 182 | [hbox setDefaultMinXMargin: 10]; 183 | 184 | [hbox addView: [self makeTextFieldWithLabel: name] 185 | enablingXResizing: YES]; 186 | [hbox addView: [self makeColorWellWithName: name isSystem: YES state: 0] 187 | enablingXResizing: NO]; 188 | 189 | [hbox setAutoresizingMask: NSViewWidthSizable]; 190 | [vbox addView: hbox]; 191 | } 192 | 193 | return vbox; 194 | } 195 | 196 | - (GSVbox *) makeExtraColorListVbox 197 | { 198 | GSVbox *vbox = [[GSVbox new] autorelease]; 199 | int i; 200 | int count = [extraColorNames count]; 201 | 202 | [vbox setDefaultMinYMargin: 2]; 203 | [vbox setBorder: 2]; 204 | 205 | for (i = 0; i < count; i++) 206 | { 207 | GSHbox *hbox = [[[GSHbox alloc] init] autorelease]; 208 | NSString *name = [extraColorNames objectAtIndex: i]; 209 | 210 | [hbox setDefaultMinXMargin: 10]; 211 | 212 | [hbox addView: [self makeTextFieldWithLabel: name] 213 | enablingXResizing: YES]; 214 | [hbox addView: 215 | [self makeColorWellWithName: name 216 | isSystem: NO 217 | state: GSThemeNormalState] 218 | enablingXResizing: NO]; 219 | [hbox addView: 220 | [self makeColorWellWithName: name 221 | isSystem: NO 222 | state: GSThemeSelectedState] 223 | enablingXResizing: NO]; 224 | [hbox addView: 225 | [self makeColorWellWithName: name 226 | isSystem: NO 227 | state: GSThemeHighlightedState] 228 | enablingXResizing: NO]; 229 | 230 | [hbox setAutoresizingMask: NSViewWidthSizable]; 231 | [vbox addView: hbox]; 232 | } 233 | 234 | // Labels 235 | { 236 | GSHbox *hbox = [[GSHbox alloc] init]; 237 | 238 | [hbox setDefaultMinXMargin: 10]; 239 | [hbox addView: [self makeBoldLabel: @"Name"] enablingXResizing: YES]; 240 | [hbox addView: [self makeBoldLabel: @"Normal"] enablingXResizing: NO]; 241 | [hbox addView: [self makeBoldLabel: @"Selected"] enablingXResizing: NO]; 242 | [hbox addView: [self makeBoldLabel: @"Highlighted"] enablingXResizing: NO]; 243 | [hbox setAutoresizingMask: NSViewWidthSizable]; 244 | [vbox addView: hbox]; 245 | RELEASE(hbox); 246 | } 247 | 248 | return vbox; 249 | } 250 | 251 | - (NSScrollView *) makeScrollView 252 | { 253 | NSScrollView *scrollView; 254 | GSVbox *vbox; 255 | 256 | vbox = [[GSVbox alloc] init]; 257 | [vbox addView: [self makeExtraColorListVbox]]; 258 | [vbox addView: [self makeBoldLabel: @"Extra Colors"]]; 259 | 260 | [vbox addView: [self makeSystemColorListVbox]]; 261 | [vbox addView: [self makeBoldLabel: @"System Colors"]]; 262 | 263 | scrollView 264 | = [[NSScrollView alloc] initWithFrame: NSMakeRect (0, 0, 150, 300)]; 265 | [scrollView setDocumentView: vbox]; 266 | RELEASE(vbox); 267 | [scrollView setHasHorizontalScroller: NO]; 268 | [scrollView setHasVerticalScroller: YES]; 269 | [scrollView setBorderType: NSBezelBorder]; 270 | [scrollView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)]; 271 | return AUTORELEASE(scrollView); 272 | } 273 | 274 | - (void) selectAt: (NSPoint)mouse 275 | { 276 | if (ignoreSelectAt) 277 | return; 278 | 279 | ASSIGN(inspector, [self makeScrollView]); 280 | [super selectAt: mouse]; 281 | } 282 | 283 | - (NSString*) title 284 | { 285 | return @"Colors"; 286 | } 287 | 288 | - (void) takeColorFrom: (id)sender 289 | { 290 | NSInteger tag = [sender tag]; 291 | NSColor *color = [(NSColorWell*)sender color]; 292 | 293 | if (color != nil) 294 | { 295 | NSString *name = [self nameForTag: tag]; 296 | BOOL system = [self tagIsSystem: tag]; 297 | GSThemeControlState state = [self themeControlStateForTag: tag]; 298 | 299 | ignoreSelectAt = YES; 300 | [self setColor: color forName: name isSystem: system state: state]; 301 | ignoreSelectAt = NO; 302 | } 303 | } 304 | 305 | - (NSColor *) colorForName: (NSString *)aName 306 | isSystem: (BOOL)system 307 | state: (GSThemeControlState)state 308 | { 309 | NSColor *result = nil; 310 | 311 | if (system) 312 | { 313 | result = [owner colorForKey: aName]; 314 | } 315 | else 316 | { 317 | if (state == GSThemeNormalState) 318 | { 319 | // do nothing 320 | } 321 | else if (state == GSThemeHighlightedState) 322 | { 323 | aName = [aName stringByAppendingString: @"Highlighted"]; 324 | } 325 | else if (state == GSThemeSelectedState) 326 | { 327 | aName = [aName stringByAppendingString: @"Selected"]; 328 | } 329 | else 330 | { 331 | NSLog(@"Unsupported theme state"); 332 | } 333 | result = [owner extraColorForKey: aName]; 334 | } 335 | 336 | if (result == nil) 337 | { 338 | //NSLog(@"Theme does not currently define %@", aName); 339 | 340 | // FIXME: Show a "set color" button rather than pretending the color is set to clear 341 | result = [NSColor clearColor]; 342 | } 343 | return result; 344 | } 345 | 346 | - (void) setColor: (NSColor *)aColor 347 | forName: (NSString *)aName 348 | isSystem: (BOOL)system 349 | state: (GSThemeControlState)state 350 | { 351 | if (system) 352 | { 353 | [owner setColor: aColor forKey: aName]; 354 | } 355 | else 356 | { 357 | if (state == GSThemeNormalState) 358 | { 359 | // do nothing 360 | } 361 | else if (state == GSThemeHighlightedState) 362 | { 363 | aName = [aName stringByAppendingString: @"Highlighted"]; 364 | } 365 | else if (state == GSThemeSelectedState) 366 | { 367 | aName = [aName stringByAppendingString: @"Selected"]; 368 | } 369 | else 370 | { 371 | NSLog(@"Unsupported theme state"); 372 | } 373 | [owner setExtraColor: aColor forKey: aName]; 374 | } 375 | } 376 | 377 | // Ugly: map (name, isSystem, state) tuple to an integer and back 378 | 379 | - (NSInteger) tagForName: (NSString *)aName 380 | isSystem: (BOOL)system 381 | state: (GSThemeControlState)state 382 | { 383 | const NSUInteger systemCount = [systemColorNames count]; 384 | const NSUInteger extraCount = [extraColorNames count]; 385 | 386 | NSInteger result = 0; 387 | 388 | if (system) 389 | { 390 | result = [systemColorNames indexOfObject: aName]; 391 | } 392 | else 393 | { 394 | NSInteger indexInExtraArray = [extraColorNames indexOfObject: aName]; 395 | result += (state * extraCount); 396 | result += indexInExtraArray; 397 | result += systemCount; 398 | } 399 | return result; 400 | } 401 | 402 | - (NSString *) nameForTag: (NSInteger)tag 403 | { 404 | const NSUInteger systemCount = [systemColorNames count]; 405 | const NSUInteger extraCount = [extraColorNames count]; 406 | 407 | if (tag < systemCount) 408 | { 409 | return [systemColorNames objectAtIndex: tag]; 410 | } 411 | else 412 | { 413 | tag -= systemCount; 414 | tag = tag % extraCount; 415 | return [extraColorNames objectAtIndex: tag]; 416 | } 417 | } 418 | 419 | - (BOOL) tagIsSystem: (NSInteger)tag 420 | { 421 | const NSUInteger systemCount = [systemColorNames count]; 422 | return tag < systemCount; 423 | } 424 | 425 | - (GSThemeControlState) themeControlStateForTag: (NSInteger)tag 426 | { 427 | const NSUInteger systemCount = [systemColorNames count]; 428 | const NSUInteger extraCount = [extraColorNames count]; 429 | 430 | if (tag < systemCount) 431 | { 432 | return GSThemeNormalState; 433 | } 434 | else 435 | { 436 | tag -= systemCount; 437 | return tag / extraCount; 438 | } 439 | } 440 | 441 | @end 442 | 443 | -------------------------------------------------------------------------------- /ControlElement.h: -------------------------------------------------------------------------------- 1 | /* ControlElement.h 2 | * 3 | * Copyright (C) 2006-2008 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006,2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | 26 | #import 27 | #import "ThemeElement.h" 28 | 29 | @class TilesBox; 30 | 31 | @interface ControlElement : ThemeElement 32 | { 33 | NSDictionary *images; 34 | TilesBox *tiles; 35 | NSString *className; 36 | NSString *colorName; 37 | NSString *tileName; 38 | NSDictionary *classInfo; 39 | NSDictionary *fragments; 40 | id codeDescription; 41 | id codeMenu; 42 | id colorsMenu; 43 | id colorsState; 44 | id colorsWell; 45 | id defsDescription; 46 | id defsMenu; 47 | id defsOption; 48 | id tilesHorizontal; 49 | id tilesImages; 50 | id tilesMenu; 51 | id tilesState; 52 | id tilesStyle; 53 | id tilesVertical; 54 | id tilesPreview; 55 | } 56 | - (NSString*) colorName; 57 | - (NSString*) className; // The name of the control class 58 | - (NSString*) elementName; 59 | - (GSThemeControlState) elementState; 60 | - (NSString*) imageName; 61 | - (int) style; 62 | - (void) takeCodeDelete: (id)sender; 63 | - (void) takeCodeEdit: (id)sender; 64 | - (void) takeCodeMethod: (id)sender; 65 | - (void) takeColorDelete: (id)sender; 66 | - (void) takeColorName: (id)sender; 67 | - (void) takeColorValue: (id)sender; 68 | - (void) takeTileDelete: (id)sender; 69 | - (void) takeDefsName: (id)sender; 70 | - (void) takeDefsValue: (id)sender; 71 | - (void) takeTileDelete: (id)sender; 72 | - (void) takeTileImage: (id)sender; 73 | - (void) takeTileName: (id)sender; 74 | - (void) takeTilePosition: (id)sender; 75 | - (void) takeTileStyle: (id)sender; 76 | - (NSView*) tilesPreview; 77 | @end 78 | -------------------------------------------------------------------------------- /ControlElement.m: -------------------------------------------------------------------------------- 1 | /* ControlElement.m 2 | * 3 | * Copyright (C) 2006-2008 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006,2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeDocument.h" 29 | #import "ControlElement.h" 30 | #import "CodeEditor.h" 31 | #import "TilesBox.h" 32 | 33 | @implementation ControlElement 34 | 35 | - (void) _endCodeEdit: (NSNotification*)n 36 | { 37 | NSDictionary *u = [n userInfo]; 38 | NSString *c = [u objectForKey: @"Control"]; 39 | 40 | /* Check to see if the notification is for us. 41 | */ 42 | if ([c isEqualToString: className] == YES) 43 | { 44 | NSString *m = [u objectForKey: @"Method"]; 45 | NSString *t = [u objectForKey: @"Text"]; 46 | NSString *code = [owner codeForKey: m since: 0]; 47 | 48 | t = [t stringByTrimmingSpaces]; 49 | if ([t length] == 0) t = nil; 50 | /* If the code has been changed, update the document. 51 | */ 52 | if (t != code && [t isEqual: code] == NO) 53 | { 54 | [owner setCode: t forKey: m]; 55 | [[n object] codeBuildFor: owner method: m]; 56 | } 57 | } 58 | } 59 | 60 | - (NSString*) className 61 | { 62 | return NSStringFromClass([view class]); 63 | } 64 | 65 | - (NSString*) colorName 66 | { 67 | NSString *s = [[colorsMenu selectedItem] title]; 68 | NSString *t = [[colorsState selectedItem] title]; 69 | 70 | if ([s isEqualToString: @"Normal"] == YES) 71 | { 72 | return t; 73 | } 74 | return [t stringByAppendingString: s]; 75 | } 76 | 77 | - (void) dealloc 78 | { 79 | [[NSNotificationCenter defaultCenter] removeObserver: self]; 80 | [className release]; 81 | [classInfo release]; 82 | [fragments release]; 83 | [colorName release]; 84 | [tileName release]; 85 | [super dealloc]; 86 | } 87 | 88 | - (NSString*) elementName 89 | { 90 | NSString *n = [self imageName]; 91 | 92 | if ([n hasSuffix: @"Highlighted"]) 93 | { 94 | n = [n substringToIndex: [n length] - 11]; 95 | } 96 | else if ([n hasSuffix: @"Selected"]) 97 | { 98 | n = [n substringToIndex: [n length] - 8]; 99 | } 100 | else if ([n hasSuffix: @"Disabled"]) 101 | { 102 | n = [n substringToIndex: [n length] - 8]; 103 | } 104 | return n; 105 | } 106 | 107 | - (GSThemeControlState) elementState 108 | { 109 | NSString *n = [self imageName]; 110 | 111 | if ([n hasSuffix: @"Highlighted"]) 112 | { 113 | return GSThemeHighlightedState; 114 | } 115 | else if ([n hasSuffix: @"Selected"]) 116 | { 117 | return GSThemeSelectedState; 118 | } 119 | else if ([n hasSuffix: @"Disabled"]) 120 | { 121 | return GSThemeDisabledState; 122 | } 123 | return GSThemeNormalState; 124 | } 125 | 126 | - (NSString*) imageName 127 | { 128 | return tileName; 129 | } 130 | 131 | - (id) initWithView: (NSView*)aView 132 | owner: (ThemeDocument*)aDocument 133 | { 134 | self = [super initWithView: aView owner: aDocument]; 135 | if (self != nil) 136 | { 137 | AppController *sharedController; 138 | NSDictionary *codeInfo; 139 | NSMutableDictionary *md; 140 | NSDictionary *d; 141 | NSArray *titles; 142 | unsigned count; 143 | unsigned i; 144 | 145 | sharedController = [AppController sharedController]; 146 | codeInfo = [sharedController codeInfo]; 147 | className = [[self className] retain]; 148 | 149 | /* Get information about code/makefile fragments. 150 | */ 151 | md = [NSMutableDictionary dictionary]; 152 | d = [codeInfo objectForKey: className]; 153 | if (d == nil) 154 | { 155 | NSRunAlertPanel(_(@"Control not supported"), 156 | _(@"Support for %@ is not yet implemented"), 157 | nil, nil, nil, className); 158 | } 159 | classInfo = [d copy]; 160 | d = [d objectForKey: @"Fragments"]; 161 | 162 | /* Now set up a menu to edit those fragments. 163 | */ 164 | [codeMenu removeAllItems]; 165 | if ([d count] > 0) 166 | { 167 | NSArray *names = [d allKeys]; 168 | 169 | [md addEntriesFromDictionary: d]; 170 | names = [names sortedArrayUsingSelector: @selector(compare:)]; 171 | [codeMenu addItemsWithTitles: names]; 172 | } 173 | else 174 | { 175 | [codeMenu addItemWithTitle: _(@"Not applicable")]; 176 | } 177 | 178 | if ([md count] > 0) 179 | { 180 | /* Only add generic items if we actually have some methods. 181 | */ 182 | d = [codeInfo objectForKey: @"Generic"]; 183 | d = [d objectForKey: @"Fragments"]; 184 | if ([d count] > 0) 185 | { 186 | NSArray *names = [d allKeys]; 187 | 188 | [md addEntriesFromDictionary: d]; 189 | names = [names sortedArrayUsingSelector: @selector(compare:)]; 190 | [codeMenu addItemsWithTitles: names]; 191 | } 192 | } 193 | fragments = [md copy]; 194 | [self takeCodeMethod: codeMenu]; 195 | 196 | /* Take note of ending of editing. 197 | */ 198 | [[NSNotificationCenter defaultCenter] 199 | addObserver: self 200 | selector: @selector(_endCodeEdit:) 201 | name: @"CodeEditDone" 202 | object: [CodeEditor codeEditor]]; 203 | 204 | /* view for preview of images. 205 | */ 206 | tiles = [[TilesBox alloc] 207 | initWithFrame: [[tilesPreview contentView] frame]]; 208 | [tiles setOwner: self]; 209 | [tilesPreview setContentView: tiles]; 210 | RELEASE(tiles); 211 | 212 | /* Create view in which to draw image 213 | */ 214 | NSAssert(tilesImages != nil, NSInternalInconsistencyException); 215 | tiles = [[TilesBox alloc] 216 | initWithFrame: [[tilesImages contentView] frame]]; 217 | [tiles setOwner: self]; 218 | [tilesImages setContentView: tiles]; 219 | RELEASE(tiles); 220 | 221 | titles = [[[classInfo objectForKey: @"TileElements"] allKeys] 222 | sortedArrayUsingSelector: @selector(compare:)]; 223 | [tilesMenu removeAllItems]; 224 | count = [titles count]; 225 | if (count > 0) 226 | { 227 | for (i = 0; i < count; i++) 228 | { 229 | NSString *title = [titles objectAtIndex: i]; 230 | 231 | [tilesMenu insertItemWithTitle: title atIndex: i]; 232 | } 233 | } 234 | else 235 | { 236 | [tilesMenu addItemWithTitle: _(@"Not applicable")]; 237 | } 238 | 239 | /* Select the first image and make it active. 240 | */ 241 | [tilesMenu selectItemAtIndex: 0]; 242 | [self takeTileStyle: tilesStyle]; 243 | [self takeTileName: tilesMenu]; 244 | 245 | titles = [[[classInfo objectForKey: @"ColorElements"] allKeys] 246 | sortedArrayUsingSelector: @selector(compare:)]; 247 | [colorsMenu removeAllItems]; 248 | count = [titles count]; 249 | if (count > 0) 250 | { 251 | for (i = 0; i < count; i++) 252 | { 253 | NSString *title = [titles objectAtIndex: i]; 254 | 255 | [colorsMenu insertItemWithTitle: title atIndex: i]; 256 | } 257 | } 258 | else 259 | { 260 | [colorsMenu addItemWithTitle: _(@"Not applicable")]; 261 | } 262 | /* Select the color image and make it active. 263 | */ 264 | [colorsMenu selectItemAtIndex: 0]; 265 | [self takeColorName: colorsMenu]; 266 | 267 | /* Set up the defaults menu. 268 | */ 269 | d = [classInfo objectForKey: @"Defaults"]; 270 | titles = [[d allKeys] sortedArrayUsingSelector: @selector(compare:)]; 271 | [defsMenu removeAllItems]; 272 | count = [titles count]; 273 | if (count > 0) 274 | { 275 | for (i = 0; i < count; i++) 276 | { 277 | NSString *title = [titles objectAtIndex: i]; 278 | 279 | [defsMenu insertItemWithTitle: title atIndex: i]; 280 | } 281 | } 282 | else 283 | { 284 | [defsMenu addItemWithTitle: _(@"Not applicable")]; 285 | } 286 | [defsMenu selectItemAtIndex: 0]; 287 | [self takeDefsName: defsMenu]; 288 | } 289 | return self; 290 | } 291 | 292 | - (void) selectAt: (NSPoint)mouse 293 | { 294 | [super selectAt: mouse]; 295 | 296 | /* FIXME ... should probably have a subclass to handle NSScroller 297 | */ 298 | if ([view isKindOfClass: [NSScroller class]]) 299 | { 300 | NSRect frame; 301 | NSScrollerPart part; 302 | NSString *value; 303 | 304 | part = [(NSScroller*)view testPart: 305 | [view convertPoint: mouse toView: nil]]; 306 | frame = [view frame]; 307 | 308 | if (frame.size.width > frame.size.height) 309 | { 310 | switch (part) 311 | { 312 | case NSScrollerKnob: 313 | value = @"GSScrollerHorizontalKnob"; 314 | break; 315 | case NSScrollerKnobSlot: 316 | value = @"GSScrollerHorizontalSlot"; 317 | break; 318 | case NSScrollerDecrementLine: 319 | value = @"GSScrollerLeftArrow"; 320 | break; 321 | case NSScrollerIncrementLine: 322 | value = @"GSScrollerRightArrow"; 323 | break; 324 | default: 325 | value = nil; 326 | } 327 | } 328 | else 329 | { 330 | switch (part) 331 | { 332 | case NSScrollerKnob: 333 | value = @"GSScrollerVerticalKnob"; 334 | break; 335 | case NSScrollerKnobSlot: 336 | value = @"GSScrollerVerticalSlot"; 337 | break; 338 | case NSScrollerDecrementLine: 339 | value = @"GSScrollerUpArrow"; 340 | break; 341 | case NSScrollerIncrementLine: 342 | value = @"GSScrollerDownArrow"; 343 | break; 344 | default: 345 | value = nil; 346 | } 347 | } 348 | if (value != nil) 349 | { 350 | [tilesMenu selectItem: [tilesMenu itemWithTitle: value]]; 351 | [self takeTileName: tilesMenu]; 352 | [colorsMenu selectItem: [colorsMenu itemWithTitle: value]]; 353 | [self takeColorName: colorsMenu]; 354 | } 355 | } 356 | } 357 | 358 | - (int) style 359 | { 360 | int s = [[tilesStyle selectedItem] tag]; 361 | 362 | if (s < 0) s = (-1 - s); 363 | 364 | return s; 365 | } 366 | 367 | - (void) takeCodeDelete: (id)sender 368 | { 369 | NSString *method = [[codeMenu selectedItem] title]; 370 | NSString *code = [owner codeForKey: method since: 0]; 371 | 372 | if (code != nil) 373 | { 374 | NSNotification *n; 375 | NSDictionary *userInfo; 376 | 377 | /* Remove the code by faking an endo fo code editing which 378 | * returns an empty document. 379 | */ 380 | userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 381 | className, @"Control", 382 | method, @"Method", 383 | @"", @"Text", 384 | nil]; 385 | n = [NSNotification notificationWithName: @"CodeEditDone" 386 | object: [CodeEditor codeEditor] 387 | userInfo: userInfo]; 388 | [self _endCodeEdit: n]; 389 | } 390 | } 391 | 392 | 393 | - (void) takeCodeEdit: (id)sender 394 | { 395 | NSString *method = [[codeMenu selectedItem] title]; 396 | NSString *code = [owner codeForKey: method since: 0]; 397 | 398 | if (code == nil) 399 | { 400 | NSString *path; 401 | 402 | path = [method stringByReplacingString: @":" withString: @"_"]; 403 | path = [[NSBundle mainBundle] pathForResource: path ofType: @"txt"]; 404 | if (path == nil) 405 | { 406 | NSRunAlertPanel(_(@"Problem editing method"), 407 | _(@"No template found for method %@"), 408 | nil, nil, nil, method); 409 | return; 410 | } 411 | code = [NSString stringWithContentsOfFile: path]; 412 | } 413 | [[CodeEditor codeEditor] editText: code control: className method: method]; 414 | } 415 | 416 | 417 | - (void) takeCodeMethod: (id)sender 418 | { 419 | NSString *method = [[sender selectedItem] title]; 420 | NSString *helpText = [fragments objectForKey: method]; 421 | 422 | if (helpText == nil) helpText = @"No methods available for this control"; 423 | [codeDescription setText: helpText]; 424 | [codeDescription setEditable: NO]; 425 | } 426 | 427 | 428 | - (void) takeColorDelete: (id)sender 429 | { 430 | [owner setExtraColor: nil forKey: colorName]; 431 | } 432 | 433 | 434 | - (void) takeColorName: (id)sender 435 | { 436 | NSString *s; 437 | NSString *t; 438 | NSColor *c; 439 | 440 | s = [[colorsMenu selectedItem] title]; 441 | if (sender == colorsMenu) 442 | { 443 | unsigned count; 444 | unsigned i; 445 | NSArray *titles; 446 | 447 | titles = [[[classInfo objectForKey: @"ColorElements"] objectForKey: s] 448 | objectForKey: @"States"]; 449 | if (titles == nil && [s length] > 0) 450 | { 451 | titles = [NSArray arrayWithObject: @"Normal"]; 452 | } 453 | count = [titles count]; 454 | [colorsState removeAllItems]; 455 | for (i = 0; i < count; i++) 456 | { 457 | NSString *title = [titles objectAtIndex: i]; 458 | 459 | [colorsState insertItemWithTitle: title atIndex: i]; 460 | } 461 | [colorsState selectItemAtIndex: 0]; 462 | } 463 | 464 | t = [[colorsState selectedItem] title]; 465 | if ([t isEqualToString: @"Normal"] == NO) 466 | { 467 | s = [s stringByAppendingString: t]; 468 | } 469 | if ([colorName isEqualToString: s] == YES) 470 | { 471 | return; // Unchanged. 472 | } 473 | ASSIGN(colorName, s); 474 | c = [owner extraColorForKey: colorName]; 475 | [colorsWell setColor: c]; 476 | } 477 | 478 | 479 | - (void) takeColorValue: (id)sender 480 | { 481 | [owner setExtraColor: [sender color] forKey: colorName]; 482 | } 483 | 484 | 485 | - (void) takeDefsName: (id)sender 486 | { 487 | NSString *s; 488 | NSString *n; 489 | NSDictionary *d; 490 | NSArray *a; 491 | unsigned c; 492 | unsigned i; 493 | unsigned p; 494 | 495 | s = [sender stringValue]; // get default title 496 | d = [classInfo objectForKey: @"Defaults"]; // get config for class 497 | d = [d objectForKey: s]; // get config for default 498 | n = [d objectForKey: @"Name"]; 499 | s = [d objectForKey: @"Description"]; 500 | if ([s length] > 0) 501 | { 502 | [defsDescription setText: s]; 503 | } 504 | else 505 | { 506 | [defsDescription setText: @"No options available for this control"]; 507 | } 508 | d = [d objectForKey: @"Options"]; 509 | a = [[d allKeys] sortedArrayUsingSelector: @selector(compare:)]; 510 | [defsOption removeAllItems]; 511 | c = [a count]; 512 | i = p = 0; 513 | if (c > 0) 514 | { 515 | s = [owner defaultForKey: n]; // Get current value fo default. 516 | [defsOption insertItemWithTitle: @"Default" atIndex: 0]; 517 | while (i < c) 518 | { 519 | NSString *title = [a objectAtIndex: i++]; 520 | 521 | [defsOption insertItemWithTitle: title atIndex: i]; 522 | if (s != nil && [[d objectForKey: title] isEqual: s] == YES) 523 | { 524 | 525 | /* If this item is the same as the current value of the default, 526 | * we should make it the selected item. 527 | */ 528 | p = i; 529 | } 530 | } 531 | } 532 | [defsOption selectItemAtIndex: p]; 533 | } 534 | 535 | - (void) takeDefsValue: (id)sender 536 | { 537 | NSDictionary *d; 538 | NSString *n; 539 | NSString *s; 540 | 541 | s = [defsMenu stringValue]; // get default title 542 | d = [classInfo objectForKey: @"Defaults"]; // get config for class 543 | d = [d objectForKey: s]; // get config for default 544 | n = [d objectForKey: @"Name"]; // get default name 545 | d = [d objectForKey: @"Options"]; // get options config 546 | s = [sender stringValue]; // get option title 547 | s = [d objectForKey: s]; // get option value 548 | if (n != nil) 549 | { 550 | [owner setDefault: s forKey: n]; // set new value 551 | } 552 | } 553 | 554 | 555 | 556 | - (void) takeTileDelete: (id)sender 557 | { 558 | [owner setTiles: [self imageName] 559 | withPath: @"" 560 | fillStyle: nil 561 | hDivision: 0 562 | vDivision: 0]; 563 | DESTROY(tileName); 564 | [self takeTileName: tilesMenu]; 565 | } 566 | 567 | 568 | - (void) takeTileImage: (id)sender 569 | { 570 | NSArray *fileTypes = [NSImage imageFileTypes]; 571 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 572 | int result; 573 | 574 | [oPanel setAllowsMultipleSelection: NO]; 575 | [oPanel setCanChooseFiles: YES]; 576 | [oPanel setCanChooseDirectories: NO]; 577 | result = [oPanel runModalForDirectory: NSHomeDirectory() 578 | file: nil 579 | types: fileTypes]; 580 | if (result == NSOKButton) 581 | { 582 | NSString *path = [oPanel filename]; 583 | NSImage *image = nil; 584 | 585 | NS_DURING 586 | { 587 | image = [[NSImage alloc] initWithContentsOfFile: path]; 588 | } 589 | NS_HANDLER 590 | { 591 | NSString *message = [localException reason]; 592 | NSRunAlertPanel(_(@"Problem loading image"), 593 | message, 594 | nil, nil, nil); 595 | } 596 | NS_ENDHANDLER 597 | if (image != nil) 598 | { 599 | NSSize s = [image size]; 600 | int h = (int)s.width; 601 | int v = (int)s.height; 602 | 603 | RELEASE(image); 604 | [owner setTiles: [self imageName] 605 | withPath: path 606 | fillStyle: GSThemeStringFromFillStyle([self style]) 607 | hDivision: (h / 3) 608 | vDivision: (v / 3)]; 609 | DESTROY(tileName); 610 | [self takeTileName: tilesMenu]; 611 | } 612 | } 613 | } 614 | 615 | 616 | - (void) takeTileName: (id)sender 617 | { 618 | NSImage *image; 619 | NSString *f; 620 | NSString *s; 621 | NSString *t; 622 | int h; 623 | int v; 624 | 625 | s = [[tilesMenu selectedItem] title]; 626 | if (sender == tilesMenu) 627 | { 628 | unsigned count; 629 | unsigned i; 630 | NSArray *titles; 631 | 632 | titles = [[[classInfo objectForKey: @"TileElements"] objectForKey: s] 633 | objectForKey: @"States"]; 634 | if (titles == nil && [s length] > 0) 635 | { 636 | titles = [NSArray arrayWithObject: @"Normal"]; 637 | } 638 | count = [titles count]; 639 | [tilesState removeAllItems]; 640 | for (i = 0; i < count; i++) 641 | { 642 | NSString *title = [titles objectAtIndex: i]; 643 | 644 | [tilesState insertItemWithTitle: title atIndex: i]; 645 | } 646 | [tilesState selectItemAtIndex: 0]; 647 | } 648 | 649 | t = [[tilesState selectedItem] title]; 650 | if ([t isEqualToString: @"Normal"] == NO) 651 | { 652 | s = [s stringByAppendingString: t]; 653 | } 654 | if ([tileName isEqualToString: s] == YES) 655 | { 656 | return; // Unchanged. 657 | } 658 | ASSIGN(tileName, s); 659 | image = [owner tiles: [self imageName] 660 | fillStyle: &f 661 | hDivision: &h 662 | vDivision: &v]; 663 | if (image != nil) 664 | { 665 | NSSize s = [image size]; 666 | int mh = (int)(s.height / 2); 667 | int mv = (int)(s.width / 2); 668 | 669 | [tilesHorizontal setMinValue: 1.0]; 670 | [tilesVertical setMinValue: 1.0]; 671 | [tilesHorizontal setMaxValue: (double)mh]; 672 | [tilesVertical setMaxValue: (double)mv]; 673 | [tilesHorizontal setIntValue: h]; 674 | [tilesVertical setIntValue: v]; 675 | [tilesHorizontal setNumberOfTickMarks: mh]; 676 | [tilesVertical setNumberOfTickMarks: mv]; 677 | [tilesHorizontal setAllowsTickMarkValuesOnly: YES]; 678 | [tilesVertical setAllowsTickMarkValuesOnly: YES]; 679 | if (f == nil) f = GSThemeStringFromFillStyle(GSThemeFillStyleNone); 680 | [tilesStyle selectItemWithTag: GSThemeFillStyleFromString(f)]; 681 | } 682 | [tiles setNeedsDisplay: YES]; 683 | } 684 | 685 | 686 | - (void) takeTilePosition: (id)sender 687 | { 688 | [owner setTiles: [self imageName] 689 | withPath: nil 690 | fillStyle: GSThemeStringFromFillStyle([self style]) 691 | hDivision: [tilesHorizontal intValue] 692 | vDivision: [tilesVertical intValue]]; 693 | [tiles setNeedsDisplay: YES]; 694 | } 695 | 696 | 697 | - (void) takeTileStyle: (id)sender 698 | { 699 | NSInteger s = [sender tag]; 700 | 701 | [owner setTiles: [self imageName] 702 | withPath: nil 703 | fillStyle: GSThemeStringFromFillStyle([self style]) 704 | hDivision: [tilesHorizontal intValue] 705 | vDivision: [tilesVertical intValue]]; 706 | 707 | /* Change tiles box to be flipped or non-flipped as necessary, 708 | * then get it to redraw in the new style. 709 | * NB. To use this code (debug purposes) you need to edit the TiledElement 710 | * GORM file so that the popup menu for selecting the display style has 711 | * extra buttons (with negstive tags) for drawing in a flipped view. 712 | */ 713 | if (s < 0) 714 | { 715 | if ([tiles isKindOfClass: [FlippedTilesBox class]] == NO) 716 | { 717 | tiles = [[FlippedTilesBox alloc] initWithFrame: [tiles frame]]; 718 | [tiles setOwner: self]; 719 | [tilesImages setContentView: tiles]; 720 | RELEASE(tiles); 721 | } 722 | } 723 | else 724 | { 725 | if ([tiles isKindOfClass: [FlippedTilesBox class]] == YES) 726 | { 727 | tiles = [[TilesBox alloc] initWithFrame: [tiles frame]]; 728 | [tiles setOwner: self]; 729 | [tilesImages setContentView: tiles]; 730 | RELEASE(tiles); 731 | } 732 | } 733 | [tiles setNeedsDisplay: YES]; 734 | } 735 | 736 | - (NSView*) tilesPreview 737 | { 738 | return (NSView*)tilesPreview; 739 | } 740 | @end 741 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # 2 | # GNUmakefile - Generated by ProjectCenter 3 | # 4 | ifeq ($(GNUSTEP_MAKEFILES),) 5 | GNUSTEP_MAKEFILES := $(shell gnustep-config --variable=GNUSTEP_MAKEFILES 2>/dev/null) 6 | ifeq ($(GNUSTEP_MAKEFILES),) 7 | $(warning ) 8 | $(warning Unable to obtain GNUSTEP_MAKEFILES setting from gnustep-config!) 9 | $(warning Perhaps gnustep-make is not properly installed,) 10 | $(warning so gnustep-config is not in your PATH.) 11 | $(warning ) 12 | $(warning Your PATH is currently $(PATH)) 13 | $(warning ) 14 | endif 15 | endif 16 | ifeq ($(GNUSTEP_MAKEFILES),) 17 | $(error You need to set GNUSTEP_MAKEFILES before compiling!) 18 | endif 19 | 20 | include $(GNUSTEP_MAKEFILES)/common.make 21 | 22 | # 23 | # Application 24 | # 25 | VERSION = 0.2 26 | PACKAGE_NAME = Thematic 27 | APP_NAME = Thematic 28 | Thematic_APPLICATION_ICON = Thematic.png 29 | GNUSTEP_INSTALLATION_DOMAIN = SYSTEM 30 | 31 | 32 | # 33 | # Resource files 34 | # 35 | Thematic_RESOURCE_FILES = \ 36 | Resources/Thematic.gorm \ 37 | Resources/ThemeInspector.gorm \ 38 | Resources/ColorElement.gorm \ 39 | Resources/ThemeDocument.gorm \ 40 | Resources/ImageElement.gorm \ 41 | Resources/WindowsElement.gorm \ 42 | Resources/MenusElement.gorm \ 43 | Resources/MiscElement.gorm \ 44 | Resources/ControlElement.gorm \ 45 | Resources/CodeEditor.gorm \ 46 | Resources/Thematic.png \ 47 | Resources/ThematicHelp.rtf \ 48 | Resources/CodeInfo.plist \ 49 | Resources/drawButton_in_view_style_state_.txt \ 50 | Resources/CommonMethods.txt \ 51 | Resources/IncludeHeaders.txt \ 52 | Resources/MakeAdditions.txt \ 53 | Resources/VariableDeclarations.txt 54 | 55 | 56 | # 57 | # Header files 58 | # 59 | Thematic_HEADER_FILES = \ 60 | AppController.h \ 61 | ThemeDocument.h \ 62 | ThemeElement.h \ 63 | ColorElement.h \ 64 | ImageElement.h \ 65 | MenusElement.h \ 66 | WindowsElement.h \ 67 | MiscElement.h \ 68 | ControlElement.h \ 69 | TilesBox.h \ 70 | CodeEditor.h \ 71 | MenuItemElement.h \ 72 | PreviewElement.h 73 | 74 | # 75 | # Objective-C Class files 76 | # 77 | Thematic_OBJC_FILES = \ 78 | AppController.m \ 79 | ThemeDocument.m \ 80 | ThemeElement.m \ 81 | ImageElement.m \ 82 | MenusElement.m \ 83 | WindowsElement.m \ 84 | MiscElement.m \ 85 | ControlElement.m \ 86 | ColorElement.m \ 87 | TilesBox.m \ 88 | CodeEditor.m \ 89 | MenuItemElement.m \ 90 | PreviewElement.m 91 | 92 | # 93 | # Other sources 94 | # 95 | Thematic_OBJC_FILES += \ 96 | main.m 97 | 98 | # 99 | # Makefiles 100 | # 101 | -include GNUmakefile.preamble 102 | include $(GNUSTEP_MAKEFILES)/aggregate.make 103 | include $(GNUSTEP_MAKEFILES)/application.make 104 | -include GNUmakefile.postamble 105 | -------------------------------------------------------------------------------- /GNUmakefile.postamble: -------------------------------------------------------------------------------- 1 | # 2 | # GNUmakefile.postamble - Generated by ProjectCenter 3 | # 4 | 5 | # Things to do before compiling 6 | # before-all:: 7 | 8 | # Things to do after compiling 9 | # after-all:: 10 | 11 | # Things to do before installing 12 | # before-install:: 13 | 14 | # Things to do after installing 15 | # after-install:: 16 | 17 | # Things to do before uninstalling 18 | # before-uninstall:: 19 | 20 | # Things to do after uninstalling 21 | # after-uninstall:: 22 | 23 | # Things to do before cleaning 24 | # before-clean:: 25 | 26 | # Things to do after cleaning 27 | # after-clean:: 28 | 29 | # Things to do before distcleaning 30 | # before-distclean:: 31 | 32 | # Things to do after distcleaning 33 | # after-distclean:: 34 | 35 | # Things to do before checking 36 | # before-check:: 37 | 38 | # Things to do after checking 39 | # after-check:: 40 | 41 | -------------------------------------------------------------------------------- /GNUmakefile.preamble: -------------------------------------------------------------------------------- 1 | # 2 | # GNUmakefile.preamble - Generated by ProjectCenter 3 | # 4 | 5 | # Additional flags to pass to the preprocessor 6 | ADDITIONAL_CPPFLAGS += 7 | 8 | # Additional flags to pass to Objective C compiler 9 | ADDITIONAL_OBJCFLAGS += 10 | 11 | # Additional flags to pass to C compiler 12 | ADDITIONAL_CFLAGS += 13 | 14 | # Additional flags to pass to the linker 15 | ADDITIONAL_LDFLAGS += 16 | 17 | # Additional include directories the compiler should search 18 | ADDITIONAL_INCLUDE_DIRS += 19 | 20 | # Additional library directories the linker should search 21 | ADDITIONAL_LIB_DIRS += 22 | 23 | # Additional GUI libraries to link 24 | ADDITIONAL_GUI_LIBS += 25 | 26 | -------------------------------------------------------------------------------- /ImageElement.h: -------------------------------------------------------------------------------- 1 | /* ImageElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import "ThemeElement.h" 26 | 27 | @class ImagesView; 28 | 29 | @interface ImageElement : ThemeElement 30 | { 31 | NSInteger selectedTag; 32 | NSMutableArray *texts; 33 | NSMutableArray *views; 34 | ImagesView *imagesView; 35 | ImagesView *systemView; // Tag -1 36 | NSTextView *textView; // Tag -2 37 | id scrollView; 38 | id description; 39 | id deleteButton; 40 | id importButton; 41 | id collectionMenu; 42 | } 43 | - (void) deleteImage: (id)sender; 44 | - (void) importImage: (id)sender; 45 | - (void) switchCollection: (id)sender; 46 | @end 47 | 48 | -------------------------------------------------------------------------------- /ImageElement.m: -------------------------------------------------------------------------------- 1 | /* ImageElement.m 2 | * 3 | * Copyright (C) 2006-2020 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Riccardo Mottola 7 | * Date: 2006 8 | * 9 | * This file is part of GNUstep. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 24 | */ 25 | 26 | #import 27 | #import 28 | #import "AppController.h" 29 | #import "ThemeDocument.h" 30 | #import "ImageElement.h" 31 | 32 | @interface ImageInfo : NSObject 33 | { 34 | NSImage *original; 35 | NSString *app; 36 | NSString *name; 37 | NSString *path; 38 | NSString *description; // not retained 39 | } 40 | - (NSString*) app; 41 | - (NSString*) description; 42 | - (NSImage*) image; 43 | - (id) initWithImage: (NSImage*)i 44 | description: (NSString*)d 45 | name: (NSString*)n 46 | app: (NSString*)a; 47 | - (NSString*) name; 48 | - (NSString*) path; 49 | - (void) revert; 50 | - (void) setCurrentImage: (NSImage*)i 51 | atPath: (NSString*)p; 52 | @end 53 | 54 | @implementation ImageInfo 55 | 56 | - (NSString*) app 57 | { 58 | return app; 59 | } 60 | 61 | - (void) dealloc 62 | { 63 | RELEASE(original); 64 | RELEASE(description); 65 | RELEASE(name); 66 | RELEASE(path); 67 | RELEASE(app); 68 | [super dealloc]; 69 | } 70 | 71 | - (NSString*) description 72 | { 73 | return description; 74 | } 75 | 76 | - (NSImage*) image 77 | { 78 | return original; 79 | } 80 | 81 | - (id) initWithImage: (NSImage*)i 82 | description: (NSString*)d 83 | name: (NSString*)n 84 | app: (NSString*)a 85 | { 86 | ASSIGN(original, i); 87 | ASSIGN(description, d); 88 | ASSIGNCOPY(app, a); 89 | ASSIGNCOPY(name, n); 90 | return self; 91 | } 92 | 93 | - (NSString*) name 94 | { 95 | return name; 96 | } 97 | 98 | - (NSString*) path 99 | { 100 | return path; 101 | } 102 | 103 | - (void) revert 104 | { 105 | NSString *key; 106 | 107 | DESTROY(path); 108 | key = [self name]; 109 | if (nil != app) key = [app stringByAppendingPathComponent: key]; 110 | [[[AppController sharedController] selectedDocument] setImage: nil 111 | forKey: key]; 112 | } 113 | 114 | - (void) setCurrentImage: (NSImage*)i 115 | atPath: (NSString*)p 116 | { 117 | NSString *key; 118 | 119 | ASSIGN(path, p); 120 | key = [self name]; 121 | if (nil != app) key = [app stringByAppendingPathComponent: key]; 122 | [[[AppController sharedController] selectedDocument] setImage: path 123 | forKey: key]; 124 | } 125 | @end 126 | 127 | @interface DummyInfo : ImageInfo 128 | @end 129 | @implementation DummyInfo 130 | - (NSString*) name 131 | { 132 | return @""; 133 | } 134 | - (void) revert 135 | { 136 | return; 137 | } 138 | @end 139 | 140 | 141 | @interface ImagesView : NSMatrix 142 | { 143 | NSMutableArray *objects; 144 | ImageInfo *selected; 145 | NSTextField *description; 146 | NSString *lastPath; 147 | NSString *bundleIdentifier; 148 | } 149 | - (void) addObject: (ImageInfo*)anObject; 150 | - (void) makeSelectionVisible: (BOOL)flag; 151 | - (void) refreshCells; 152 | - (void) selectObject: (ImageInfo*)obj; 153 | - (ImageInfo*) selected; 154 | - (void) setBundleIdentifier: (NSString*)i; 155 | - (void) setDescription: (NSTextField*)d; 156 | @end 157 | 158 | @implementation ImagesView 159 | 160 | 161 | - (BOOL) acceptsFirstMouse: (NSEvent*)theEvent 162 | { 163 | return YES; /* Ensure we get initial mouse down event. */ 164 | } 165 | 166 | - (void) addObject: (ImageInfo*)anObject 167 | { 168 | if (anObject != nil 169 | && [objects indexOfObjectIdenticalTo: anObject] == NSNotFound) 170 | { 171 | [objects addObject: anObject]; 172 | [self refreshCells]; 173 | } 174 | } 175 | 176 | - (void) changeSelection: (id)sender 177 | { 178 | NSInteger row = [self selectedRow]; 179 | NSInteger col = [self selectedColumn]; 180 | NSInteger index = row * [self numberOfColumns] + col; 181 | id obj = nil; 182 | 183 | if (index >= 0 && index < [objects count]) 184 | { 185 | obj = [objects objectAtIndex: index]; 186 | [self selectObject: obj]; 187 | } 188 | } 189 | 190 | - (void) dealloc 191 | { 192 | RELEASE(objects); 193 | RELEASE(lastPath); 194 | RELEASE(bundleIdentifier); 195 | [super dealloc]; 196 | } 197 | 198 | - (void) deleteImage: (id)sender 199 | { 200 | if (NO == [selected isKindOfClass: [DummyInfo class]]) 201 | { 202 | [selected revert]; 203 | [self makeSelectionVisible: NO]; 204 | if (nil != bundleIdentifier) 205 | { 206 | [objects removeObjectIdenticalTo: selected]; 207 | [self refreshCells]; 208 | selected = [objects objectAtIndex: 0]; // Add new image 209 | } 210 | [self selectObject: selected]; 211 | } 212 | } 213 | 214 | - (void) importImage: (id)sender 215 | { 216 | NSArray *fileTypes = [NSImage imageFileTypes]; 217 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 218 | NSInteger result; 219 | 220 | [oPanel setAllowsMultipleSelection: NO]; 221 | [oPanel setCanChooseFiles: YES]; 222 | [oPanel setCanChooseDirectories: NO]; 223 | result = [oPanel runModalForDirectory: lastPath 224 | file: nil 225 | types: fileTypes]; 226 | if (result == NSOKButton) 227 | { 228 | NSString *path = [oPanel filename]; 229 | NSImage *image = nil; 230 | 231 | NS_DURING 232 | { 233 | image = [[NSImage alloc] initWithContentsOfFile: path]; 234 | } 235 | NS_HANDLER 236 | { 237 | NSString *message = [localException reason]; 238 | NSRunAlertPanel(_(@"Problem loading image"), 239 | message, 240 | nil, nil, nil); 241 | } 242 | NS_ENDHANDLER 243 | if (image != nil) 244 | { 245 | ASSIGN(lastPath, [path stringByDeletingLastPathComponent]); 246 | if ([selected isKindOfClass: [DummyInfo class]]) 247 | { 248 | NSString *name; 249 | 250 | name = [[path lastPathComponent] stringByDeletingPathExtension]; 251 | selected = [[ImageInfo alloc] initWithImage: image 252 | description: name 253 | name: name 254 | app: bundleIdentifier]; 255 | [self addObject: selected]; 256 | RELEASE(selected); 257 | } 258 | [selected setCurrentImage: image atPath: path]; 259 | RELEASE(image); 260 | [self refreshCells]; 261 | } 262 | } 263 | [self makeSelectionVisible: NO]; 264 | [self selectObject: selected]; 265 | } 266 | 267 | - (id) initWithFrame: (NSRect)frame 268 | { 269 | if ((self = [super initWithFrame: frame]) != nil) 270 | { 271 | id proto; 272 | 273 | [self setAutosizesCells: NO]; 274 | [self setCellSize: NSMakeSize(72,72)]; 275 | [self setIntercellSpacing: NSMakeSize(8,8)]; 276 | [self setAutoresizingMask: NSViewMinYMargin|NSViewWidthSizable]; 277 | [self setMode: NSRadioModeMatrix]; 278 | 279 | objects = [[NSMutableArray alloc] init]; 280 | proto = [[NSButtonCell alloc] init]; 281 | [proto setBordered: NO]; 282 | [proto setAlignment: NSCenterTextAlignment]; 283 | [proto setImagePosition: NSImageAbove]; 284 | [proto setSelectable: NO]; 285 | [proto setEditable: NO]; 286 | [self setPrototype: proto]; 287 | RELEASE(proto); 288 | 289 | [self setAction: @selector(changeSelection:)]; 290 | [self setDoubleAction: @selector(importImage:)]; 291 | [self setTarget: self]; 292 | } 293 | return self; 294 | } 295 | 296 | - (void) makeSelectionVisible: (BOOL)flag 297 | { 298 | if (flag == YES && selected != nil) 299 | { 300 | unsigned pos = [objects indexOfObjectIdenticalTo: selected]; 301 | int r = pos / [self numberOfColumns]; 302 | int c = pos % [self numberOfColumns]; 303 | 304 | [self selectCellAtRow: r column: c]; 305 | } 306 | else 307 | { 308 | [self deselectAllCells]; 309 | } 310 | [self displayIfNeeded]; 311 | [[self window] flushWindow]; 312 | } 313 | 314 | - (void) refreshCells 315 | { 316 | NSUInteger count = [objects count]; 317 | NSUInteger index; 318 | NSInteger cols = 0; 319 | NSInteger rows; 320 | NSInteger width; 321 | 322 | width = [[self superview] bounds].size.width; 323 | while (width >= 72) 324 | { 325 | width -= (72 + 8); 326 | cols++; 327 | } 328 | if (cols == 0) 329 | { 330 | cols = 1; 331 | } 332 | rows = count / cols; 333 | if (rows == 0 || rows * cols != count) 334 | { 335 | rows++; 336 | } 337 | [self renewRows: rows columns: cols]; 338 | 339 | for (index = 0; index < count; index++) 340 | { 341 | ImageInfo *img = [objects objectAtIndex: index]; 342 | NSButtonCell *but = [self cellAtRow: index/cols column: index%cols]; 343 | NSImage *image; 344 | 345 | image = [img image]; 346 | if (image != nil) 347 | { 348 | [but setImage: image]; 349 | /* Make sure big images are shrunk to fit. 350 | */ 351 | if ([image size].width > 64 352 | || [image size].height > 64) 353 | { 354 | [but setImageScaling: NSImageScaleProportionallyUpOrDown]; 355 | } 356 | else 357 | { 358 | [but setImageScaling: NSImageScaleNone]; 359 | } 360 | } 361 | [but setTitle: @""]; 362 | [but setShowsStateBy: NSChangeGrayCellMask]; 363 | [but setHighlightsBy: NSChangeGrayCellMask]; 364 | } 365 | while (index < rows * cols) 366 | { 367 | NSButtonCell *but = [self cellAtRow: index/cols column: index%cols]; 368 | 369 | [but setImage: nil]; 370 | [but setTitle: @""]; 371 | [but setShowsStateBy: NSNoCellMask]; 372 | [but setHighlightsBy: NSNoCellMask]; 373 | index++; 374 | } 375 | [self setIntercellSpacing: NSMakeSize(8,8)]; 376 | [self sizeToCells]; 377 | [self setNeedsDisplay: YES]; 378 | } 379 | 380 | /* 381 | * Return the rectangle in which an objects image will be displayed. 382 | * (use window coordinates) 383 | */ 384 | - (NSRect) rectForObject: (id)anObject 385 | { 386 | NSInteger pos = [objects indexOfObjectIdenticalTo: anObject]; 387 | NSRect rect; 388 | NSInteger r; 389 | NSInteger c; 390 | 391 | if (pos == NSNotFound) 392 | return NSZeroRect; 393 | r = pos / [self numberOfColumns]; 394 | c = pos % [self numberOfColumns]; 395 | rect = [self cellFrameAtRow: r column: c]; 396 | /* 397 | * Adjust to image area. 398 | */ 399 | rect.size.height -= 15; 400 | rect = [self convertRect: rect toView: nil]; 401 | return rect; 402 | } 403 | 404 | - (void) removeObject: (id)anObject 405 | { 406 | NSInteger pos; 407 | 408 | pos = [objects indexOfObjectIdenticalTo: anObject]; 409 | if (pos == NSNotFound) 410 | { 411 | return; 412 | } 413 | [objects removeObjectAtIndex: pos]; 414 | [self refreshCells]; 415 | } 416 | 417 | - (void) resizeWithOldSuperviewSize: (NSSize)oldSize 418 | { 419 | [self refreshCells]; 420 | } 421 | 422 | - (void) selectObject: (ImageInfo*)obj 423 | { 424 | selected = obj; 425 | [description setStringValue: [obj description]]; 426 | [self makeSelectionVisible: YES]; 427 | } 428 | 429 | - (ImageInfo*) selected 430 | { 431 | return selected; 432 | } 433 | 434 | - (void) setBundleIdentifier: (NSString*)i 435 | { 436 | ASSIGN(bundleIdentifier, i); 437 | } 438 | 439 | - (void) setDescription: (NSTextField*)d 440 | { 441 | description = d; 442 | } 443 | 444 | @end 445 | 446 | 447 | 448 | @implementation ImageElement 449 | 450 | - (void) dealloc 451 | { 452 | RELEASE(texts); 453 | RELEASE(views); 454 | RELEASE(systemView); 455 | RELEASE(textView); 456 | [super dealloc]; 457 | } 458 | 459 | - (void) deleteImage: (id)sender 460 | { 461 | [imagesView deleteImage: sender]; 462 | } 463 | 464 | - (void) importImage: (id)sender 465 | { 466 | [imagesView importImage: sender]; 467 | } 468 | 469 | - (id) initWithView: (NSView*)aView 470 | owner: (ThemeDocument*)aDocument 471 | { 472 | if ((self = [super initWithView: aView owner: aDocument]) != nil) 473 | { 474 | NSRect frame; 475 | NSDictionary *apps; 476 | NSEnumerator *appEnum; 477 | NSString *app; 478 | NSInteger tag; 479 | 480 | selectedTag = -2; 481 | 482 | frame = [[scrollView documentView] frame]; 483 | frame.origin = NSZeroPoint; 484 | 485 | texts = [NSMutableArray new]; 486 | views = [NSMutableArray new]; 487 | 488 | systemView = [[ImagesView alloc] initWithFrame: frame]; 489 | [systemView setDescription: description]; 490 | 491 | textView = [[NSTextView alloc] init]; 492 | [textView setSelectable: YES]; 493 | [textView setEditable: NO]; 494 | [textView setDrawsBackground: YES]; 495 | [textView setHorizontallyResizable: NO]; 496 | [textView setVerticallyResizable: NO]; 497 | [textView setFrameSize: frame.size]; 498 | [[textView textStorage] replaceCharactersInRange: NSMakeRange(0,0) 499 | withString: @"Enter the bundle identifier of an application in order to start adding application-specific images. You may then import images to replace the named images provided and used by that application."]; 500 | 501 | imagesView = systemView; 502 | [scrollView setDocumentView: imagesView]; 503 | #define I(X,Y) {\ 504 | NSImage *i = [NSImage imageNamed: X]; \ 505 | ImageInfo *ii = [[ImageInfo alloc] initWithImage: i description: Y name: X app: nil]; \ 506 | [imagesView addObject: ii]; \ 507 | RELEASE(ii); \ 508 | } 509 | I(@"common_3DArrowDown", @"Pulldown menu marker"); 510 | I(@"common_3DArrowRight", @"Right arrow used in browsers"); 511 | I(@"common_3DArrowRightH", @"Highlighted Right arrow used in browsers"); 512 | I(@"common_ArrowDown", @"Scroller Down arrow"); 513 | I(@"common_ArrowDownH", @"Highlighted Scroller Down arrow"); 514 | I(@"common_ArrowLeft", @"Scroller Left arrow"); 515 | I(@"common_ArrowLeftH", @"Highlighted Scroller Left arrow"); 516 | I(@"common_ArrowRight", @"Scroller Right arrow"); 517 | I(@"common_ArrowRightH", @"Highlighted Scroller Right arrow"); 518 | I(@"common_ArrowUp", @"Scroller Up arrow"); 519 | I(@"common_ArrowUpH", @"Highlighted Scroller Up arrow"); 520 | I(@"common_CenterTabStop", @"Ruler mark (center tab stop)"); 521 | I(@"common_Close", @"Window Close button"); 522 | I(@"common_CloseBroken", @"Window Close button for document needing saving"); 523 | I(@"common_CloseBrokenH", @"Highlighted Window Close button for document needing saving"); 524 | I(@"common_CloseH", @"Highlighted Window Close button"); 525 | I(@"common_ColorSwatch", @"Color swatch"); 526 | I(@"common_DecimalTabStop", @"Ruler mark (decimal tab stop)"); 527 | I(@"common_Dimple", @"Vertical scroller thumb dimple"); 528 | I(@"common_DimpleHoriz", @"Horizontal scroller thumb dimple"); 529 | I(@"common_Home", @"Home directory icon"); 530 | I(@"common_LeftTabStop", @"Ruler mark (left tab stop)"); 531 | I(@"common_Miniaturize", @"Window Miniaturize button"); 532 | I(@"common_MiniaturizeH", @"Highlighted Window Miniaturize button"); 533 | I(@"common_Mount", @"Disk mount icon"); 534 | I(@"common_Nibble", @"Popup menu marker"); 535 | I(@"common_Printer", @"Printer icon (used on toolbar)"); 536 | I(@"common_RightTabStop", @"Ruler mark (right tab stop)"); 537 | I(@"common_SliderHoriz", @"Horizontal Slider"); 538 | I(@"common_SliderVert", @"Vertical Slider"); 539 | I(@"common_TabDownSelectedLeft", @"Tab view (down selected left)"); 540 | I(@"common_TabDownSelectedRight", @"Tab view (down selected right)"); 541 | I(@"common_TabDownSelectedToUnSelectedJunction", @"Tab view (down selected to unselected junction)"); 542 | I(@"common_TabDownUnSelectedJunction", @"Tab view (down unselected junction)"); 543 | I(@"common_TabDownUnSelectedLeft", @"Tab view (down unselected left)"); 544 | I(@"common_TabDownUnSelectedRight", @"Tab view (down unselected right)"); 545 | I(@"common_TabDownUnSelectedToSelectedJunction", @"Tab view (down unselected to selected junction)"); 546 | I(@"common_TabSelectedLeft", @"Tab view (selected left)"); 547 | I(@"common_TabSelectedRight", @"Tab view (selected right)"); 548 | I(@"common_TabSelectedToUnSelectedJunction", @"Tab view (selected to unselected junction)"); 549 | I(@"common_TabUnSelectToSelectedJunction", @"Tab view (unselected to selected junction)"); 550 | I(@"common_TabUnSelectedJunction", @"Tab view (unselected junction)"); 551 | I(@"common_TabUnSelectedLeft", @"Tab view (unselected left)"); 552 | I(@"common_TabUnSelectedRight", @"Tab view (unselected right)"); 553 | I(@"common_Tile", @"Icon background tile"); 554 | I(@"common_ToolbarClippedItemsMark", @"Toolbar mark for clipped items"); 555 | I(@"common_ToolbarCustomizeToolbarItem", @"Toolbar Customize item"); 556 | I(@"common_ToolbarSeparatorItem", @"Toolbar Separator item"); 557 | I(@"common_ToolbarShowColorsItem", @"Toolbar Colors item"); 558 | I(@"common_ToolbarShowFontsItem", @"Toolbar Font item"); 559 | I(@"common_Unmount", @"Disk unmount icon"); 560 | I(@"common_copyCursor", @"Cursor (dragging over view which will copy)"); 561 | I(@"common_linkCursor", @"Cursor (dragging over view which will link)"); 562 | I(@"common_noCursor", @"Cursor (dragging over view which won't accept drop)"); 563 | I(@"common_outlineCollapsed", @"Outline view marker for collapsed outline"); 564 | I(@"common_outlineExpanded", @"Outline view marker for expanded outline"); 565 | I(@"common_outlineUnexpandable", @"Outline view marker for unexpandable outline"); 566 | I(@"common_ret", @"Return/Enter key"); 567 | I(@"common_retH", @"Highlighted Return/Enter key"); 568 | I(@"common_Root_PC", @"Image of the Root computer - PC"); 569 | I(@"common_Desktop", @"Desktop Folder"); 570 | I(@"common_Folder", @"Folder"); 571 | I(@"common_DocsFolder", @"Documents Folder"); 572 | I(@"common_ImageFolder", @"Images Folder"); 573 | I(@"common_DownloadFolder", @"Downloads Folder"); 574 | I(@"common_GSFolder", @"System Folder"); 575 | I(@"common_ApplicationFolder",@"Application Folder"); 576 | I(@"common_LibraryFolder", @"Library Folder"); 577 | I(@"common_MusicFolder", @"Music Folder"); 578 | I(@"common_HomeDirectory", @"Home Directory Folder"); 579 | I(@"common_Unknown", @"Unknown File"); 580 | I(@"common_UnknownApplication", @"Unknown Application"); 581 | I(@"common_UnknownTool", @"Unknown Tool"); 582 | I(@"common_VideoFolder", @"Movie Folder"); 583 | I(@"common_RadioOn", @"Selected Radio Button"); 584 | I(@"common_RadioOff", @"Unselected Radio Button"); 585 | I(@"common_SwitchOn", @"Selected Switch Button"); 586 | I(@"common_SwitchOff", @"Unselected Switch Button"); 587 | I(@"common_RecyclerEmpty", @"Recycler bin Empty"); 588 | I(@"common_RecyclerFull", @"Recycler bin Full"); 589 | I(@"common_MultipleSelection", @"Multiple selection"); 590 | 591 | #undef I 592 | 593 | apps = [aDocument applicationImageNames]; 594 | appEnum = [[[apps allKeys] 595 | sortedArrayUsingSelector: @selector(compare:)] objectEnumerator]; 596 | tag = 0; 597 | while (nil != (app = [appEnum nextObject])) 598 | { 599 | NSEnumerator *imgEnum; 600 | NSString *img; 601 | ImagesView *appView; 602 | NSImage *i; 603 | ImageInfo *ii; 604 | 605 | appView = [[ImagesView alloc] initWithFrame: frame]; 606 | [appView setBundleIdentifier: app]; 607 | [appView setDescription: description]; 608 | [views addObject: appView]; 609 | RELEASE(appView); 610 | i = [NSImage imageNamed: @"ImageAdd"]; 611 | ii = [[DummyInfo alloc] initWithImage: i 612 | description: @"Import a new image" 613 | name: @"" 614 | app: app]; 615 | [appView addObject: ii]; 616 | RELEASE(ii); 617 | [texts addObject: app]; 618 | 619 | imgEnum = [[[apps objectForKey: app] 620 | sortedArrayUsingSelector: @selector(compare:)] objectEnumerator]; 621 | while (nil != (img = [imgEnum nextObject])) 622 | { 623 | NSString *key; 624 | 625 | key = [app stringByAppendingPathComponent: img]; 626 | img = [img stringByDeletingPathExtension]; 627 | i = [aDocument imageForKey: key]; 628 | ii = [[ImageInfo alloc] initWithImage: i 629 | description: img 630 | name: img 631 | app: app]; 632 | [appView addObject: ii]; 633 | RELEASE(ii); 634 | } 635 | [collectionMenu addItemWithTitle:app]; 636 | [[collectionMenu itemWithTitle:app] setTag:tag]; 637 | tag++; 638 | } 639 | } 640 | return self; 641 | } 642 | 643 | - (void) switchCollection: (id)sender 644 | { 645 | selectedTag = [[sender selectedItem] tag]; 646 | 647 | if (-2 == selectedTag) 648 | { 649 | imagesView = nil; 650 | [deleteButton setEnabled: NO]; 651 | [importButton setEnabled: NO]; 652 | [description setSelectable: YES]; 653 | [description setEditable: YES]; 654 | [description setBezeled: YES]; 655 | [description setDrawsBackground: YES]; 656 | [description setStringValue: @"Enter App bundle identifier"]; 657 | [description setAction: @selector(textEntered:)]; 658 | [description setTarget: self]; 659 | [description setStringValue: @"New application"]; 660 | [scrollView setDocumentView: textView]; 661 | } 662 | else 663 | { 664 | if (-1 == selectedTag) 665 | { 666 | imagesView = systemView; 667 | [description setStringValue: @"System images"]; 668 | } 669 | else 670 | { 671 | imagesView = [views objectAtIndex: selectedTag]; 672 | [description setStringValue: [@"Images specific to: " 673 | stringByAppendingString: [texts objectAtIndex: selectedTag]]]; 674 | } 675 | [scrollView setDocumentView: imagesView]; 676 | [deleteButton setEnabled: YES]; 677 | [importButton setEnabled: YES]; 678 | [description setSelectable: NO]; 679 | [description setEditable: NO]; 680 | [description setBezeled: NO]; 681 | [description setDrawsBackground: NO]; 682 | } 683 | [description display]; 684 | [[imagesView window] setTitle: 685 | [NSString stringWithFormat: @"%@ Inspector", [self title]]]; 686 | } 687 | 688 | - (void) textEntered: (id)sender 689 | { 690 | NSString *bundleIdentifier = [sender stringValue]; 691 | NSUInteger tag; 692 | 693 | bundleIdentifier = [bundleIdentifier stringByTrimmingSpaces]; 694 | if ([bundleIdentifier length] == 0) 695 | { 696 | NSLog(@"Empty bundle identifier ignored"); 697 | return; 698 | } 699 | if ([bundleIdentifier rangeOfString: @"/"].length > 0) 700 | { 701 | NSLog(@"Bundle identifier containing '/' ignored"); 702 | return; 703 | } 704 | /* Do we already have this bundle identifier? 705 | * If so, select it. 706 | */ 707 | tag = [texts indexOfObject: bundleIdentifier]; 708 | if (NSNotFound == tag) 709 | { 710 | tag = [texts count]; 711 | 712 | imagesView = [[ImagesView alloc] initWithFrame: [imagesView frame]]; 713 | [imagesView setBundleIdentifier: bundleIdentifier]; 714 | [imagesView setDescription: description]; 715 | [views addObject: imagesView]; 716 | RELEASE(imagesView); 717 | NSImage *i = [NSImage imageNamed: @"ImageAdd"]; 718 | ImageInfo *ii = [[DummyInfo alloc] initWithImage: i 719 | description: @"Import a new image" 720 | name: @"" 721 | app: bundleIdentifier]; 722 | [imagesView addObject: ii]; 723 | RELEASE(ii); 724 | [texts addObject: bundleIdentifier]; 725 | [collectionMenu addItemWithTitle: bundleIdentifier]; 726 | [[collectionMenu lastItem] setTag: tag]; 727 | } 728 | 729 | [collectionMenu selectItemAtIndex: 730 | [collectionMenu indexOfItemWithTag: tag]]; 731 | [self switchCollection: collectionMenu]; 732 | } 733 | 734 | - (NSString*) title 735 | { 736 | if (selectedTag < 0) 737 | { 738 | return @"System Images"; 739 | } 740 | return @"Application Images"; 741 | } 742 | @end 743 | 744 | -------------------------------------------------------------------------------- /MenuItemElement.h: -------------------------------------------------------------------------------- 1 | /* MenuItemElement.h 2 | * 3 | * Copyright (C) 2009 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2009 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "ControlElement.h" 28 | 29 | @interface MenuItemElement : ControlElement 30 | { 31 | } 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /MenuItemElement.m: -------------------------------------------------------------------------------- 1 | /* MenuItemElement.m 2 | * 3 | * Copyright (C) 2009 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2009 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeDocument.h" 29 | #import "MenuItemElement.h" 30 | 31 | @implementation MenuItemElement 32 | 33 | - (NSString*) className 34 | { 35 | return @"NSMenuItem"; 36 | } 37 | 38 | - (NSString*) gormName 39 | { 40 | return @"ControlElement"; 41 | } 42 | 43 | - (NSString*) title 44 | { 45 | return @"MenuItem"; 46 | } 47 | 48 | @end 49 | 50 | -------------------------------------------------------------------------------- /MenusElement.h: -------------------------------------------------------------------------------- 1 | /* MenusElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "ThemeElement.h" 28 | 29 | @interface MenusElement : ThemeElement 30 | { 31 | id arrowButton; 32 | id popup; 33 | id barColorWell; 34 | id barTitleColorWell; 35 | } 36 | - (void) takeArrowImageFrom: (id)sender; 37 | - (void) takeMenuStyleFrom: (id)sender; 38 | - (void) takeBarColorFrom: (id)sender; 39 | - (void) takeBarTitleColorFrom: (id)sender; 40 | @end 41 | 42 | -------------------------------------------------------------------------------- /MenusElement.m: -------------------------------------------------------------------------------- 1 | /* MenusElement.m 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeDocument.h" 29 | #import "MenusElement.h" 30 | 31 | @implementation MenusElement 32 | 33 | - (void) selectAt: (NSPoint)mouse 34 | { 35 | ThemeDocument *doc; 36 | NSString *val; 37 | 38 | doc = [[AppController sharedController] selectedDocument]; 39 | val = [doc defaultForKey: @"NSMenuInterfaceStyle"]; 40 | if ([val isEqualToString: @"NSWindows95InterfaceStyle"] == YES) 41 | { 42 | [popup selectItemAtIndex: [popup indexOfItemWithTag: 2]]; 43 | } 44 | else if ([val isEqualToString: @"NSMacintoshInterfaceStyle"] == YES) 45 | { 46 | [popup selectItemAtIndex: [popup indexOfItemWithTag: 1]]; 47 | } 48 | else 49 | { 50 | [popup selectItemAtIndex: [popup indexOfItemWithTag: 0]]; 51 | } 52 | [arrowButton setImage: [NSImage imageNamed: @"NSMenuArrow"]]; 53 | 54 | if ([doc extraColorForKey: @"GSMenuBar"] != nil) 55 | { 56 | [barColorWell setColor: [doc extraColorForKey: @"GSMenuBar"]]; 57 | } 58 | 59 | if ([doc extraColorForKey: @"GSMenuBarTitle"] != nil) 60 | { 61 | [barTitleColorWell setColor: [doc extraColorForKey: @"GSMenuBarTitle"]]; 62 | } 63 | 64 | [super selectAt: mouse]; 65 | } 66 | 67 | - (void) takeArrowImageFrom: (id)sender 68 | { 69 | NSArray *fileTypes = [NSImage imageFileTypes]; 70 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 71 | int result; 72 | 73 | [oPanel setAllowsMultipleSelection: NO]; 74 | [oPanel setCanChooseFiles: YES]; 75 | [oPanel setCanChooseDirectories: NO]; 76 | result = [oPanel runModalForDirectory: nil 77 | file: nil 78 | types: fileTypes]; 79 | if (result == NSOKButton) 80 | { 81 | NSString *path = [oPanel filename]; 82 | NSImage *image = nil; 83 | 84 | NS_DURING 85 | { 86 | image = [[NSImage alloc] initWithContentsOfFile: path]; 87 | } 88 | NS_HANDLER 89 | { 90 | NSString *message = [localException reason]; 91 | NSRunAlertPanel(_(@"Problem loading image"), 92 | message, 93 | nil, nil, nil); 94 | } 95 | NS_ENDHANDLER 96 | if (image != nil) 97 | { 98 | [[[AppController sharedController] selectedDocument] setImage: path 99 | forKey: @"common_3DArrowRight"]; 100 | RELEASE(image); 101 | } 102 | } 103 | } 104 | 105 | - (void) takeMenuStyleFrom: (id)sender 106 | { 107 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 108 | int style = [[sender selectedItem] tag]; 109 | 110 | switch (style) 111 | { 112 | case 2: 113 | [doc setDefault: @"NSWindows95InterfaceStyle" 114 | forKey: @"NSMenuInterfaceStyle"]; 115 | break; 116 | 117 | case 1: 118 | [doc setDefault: @"NSMacintoshInterfaceStyle" 119 | forKey: @"NSMenuInterfaceStyle"]; 120 | break; 121 | 122 | default: 123 | [doc setDefault: @"NSNextStepInterfaceStyle" 124 | forKey: @"NSMenuInterfaceStyle"]; 125 | break; 126 | } 127 | } 128 | 129 | - (void) takeBarColorFrom: (id)sender 130 | { 131 | NSColor *color = [(NSColorWell*)sender color]; 132 | 133 | if (color != nil) 134 | { 135 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 136 | [doc setExtraColor: color forKey: @"GSMenuBar"]; 137 | } 138 | } 139 | 140 | - (void) takeBarTitleColorFrom: (id)sender 141 | { 142 | NSColor *color = [(NSColorWell*)sender color]; 143 | 144 | if (color != nil) 145 | { 146 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 147 | [doc setExtraColor: color forKey: @"GSMenuBarTitle"]; 148 | } 149 | } 150 | 151 | - (NSString*) title 152 | { 153 | return @"Menus"; 154 | } 155 | @end 156 | 157 | -------------------------------------------------------------------------------- /MiscElement.h: -------------------------------------------------------------------------------- 1 | /* MiscElement.h 2 | * 3 | * Copyright (C) 2006-2013 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Riccardo Mottola 7 | * Date: 2006 8 | * 9 | * This file is part of GNUstep. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 24 | */ 25 | 26 | #import 27 | #import 28 | #import "ThemeElement.h" 29 | 30 | @interface MiscElement : ThemeElement 31 | { 32 | id iconView; 33 | id authors; 34 | id license; 35 | id details; 36 | id themeName; 37 | id themeVersion; 38 | } 39 | - (void) newVersion: (id)sender; 40 | - (void) takeIcon: (id)sender; 41 | - (void) textDidEndEditing: (NSNotification*)aNotification; 42 | @end 43 | 44 | -------------------------------------------------------------------------------- /MiscElement.m: -------------------------------------------------------------------------------- 1 | /* MiscElement.m 2 | * 3 | * Copyright (C) 2006-2013 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Riccardo Mottola 7 | * Date: 2006 8 | * 9 | * This file is part of GNUstep. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 24 | */ 25 | 26 | #import 27 | #import 28 | #import 29 | 30 | #import "AppController.h" 31 | #import "ThemeDocument.h" 32 | #import "MiscElement.h" 33 | 34 | @implementation MiscElement 35 | 36 | - (void) any: (NSNotification*)o 37 | { 38 | NSLog(@"Notified: %@", o); 39 | } 40 | 41 | - (void) didEndEditing: (id)o 42 | { 43 | NSNotification *n; 44 | 45 | /* We must record any editing changes because we have lost keyboard focus 46 | * or somesuch. 47 | */ 48 | n = [NSNotification notificationWithName: @"dummy" 49 | object: authors 50 | userInfo: nil]; 51 | [self textDidEndEditing: n]; 52 | n = [NSNotification notificationWithName: @"dummy" 53 | object: license 54 | userInfo: nil]; 55 | [self textDidEndEditing: n]; 56 | n = [NSNotification notificationWithName: @"dummy" 57 | object: details 58 | userInfo: nil]; 59 | [self textDidEndEditing: n]; 60 | } 61 | 62 | - (void) dealloc 63 | { 64 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 65 | 66 | [nc removeObserver: self]; 67 | [super dealloc]; 68 | } 69 | 70 | - (void) deselect 71 | { 72 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 73 | AppController *ctl = [AppController sharedController]; 74 | 75 | [nc removeObserver: self 76 | name: NSWindowDidResignKeyNotification 77 | object: [ctl inspector]]; 78 | [self didEndEditing: nil]; 79 | [super deselect]; 80 | } 81 | 82 | - (void) selectAt: (NSPoint)mouse 83 | { 84 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 85 | AppController *ctl = [AppController sharedController]; 86 | ThemeDocument *doc = [ctl selectedDocument]; 87 | NSDictionary *info = [doc infoDictionary]; 88 | NSArray *arr; 89 | NSString *str; 90 | int fsize = 32; 91 | 92 | [nc addObserver: self 93 | selector: @selector(didEndEditing:) 94 | name: NSWindowDidResignKeyNotification 95 | object: [ctl inspector]]; 96 | 97 | arr = [info objectForKey: @"GSThemeAuthors"]; 98 | if ([arr count] > 0) 99 | { 100 | str = [arr componentsJoinedByString: @"\n"]; 101 | [authors setString: str]; 102 | } 103 | str = [info objectForKey: @"GSThemeLicense"]; 104 | if ([str length] > 0) 105 | { 106 | [license setString: str]; 107 | } 108 | str = [info objectForKey: @"GSThemeDetails"]; 109 | if ([str length] > 0) 110 | { 111 | [details setString: str]; 112 | } 113 | [iconView setImage: [[GSTheme theme] icon]]; 114 | do 115 | { 116 | [themeName setFont: [NSFont boldSystemFontOfSize: fsize]]; 117 | fsize -= 2; 118 | [themeName sizeToFit]; 119 | } 120 | while ([themeName frame].size.width > 200 && fsize > 8); 121 | [themeName setStringValue: [[doc name] stringByDeletingPathExtension]]; 122 | str = [doc versionIncrementMajor: NO incrementMinor: NO]; 123 | [themeVersion setStringValue: str]; 124 | [super selectAt: mouse]; 125 | } 126 | 127 | - (void) newVersion: (id)sender 128 | { 129 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 130 | NSString *ver = [doc versionIncrementMajor: YES incrementMinor: NO]; 131 | 132 | [themeVersion setStringValue: ver]; 133 | } 134 | 135 | - (void) takeIcon: (id)sender 136 | { 137 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 138 | NSArray *fileTypes = [NSImage imageFileTypes]; 139 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 140 | int result; 141 | 142 | [oPanel setAllowsMultipleSelection: NO]; 143 | [oPanel setCanChooseFiles: YES]; 144 | [oPanel setCanChooseDirectories: NO]; 145 | result = [oPanel runModalForDirectory: NSHomeDirectory() 146 | file: nil 147 | types: fileTypes]; 148 | if (result == NSOKButton) 149 | { 150 | NSString *path = [oPanel filename]; 151 | NSImage *image = nil; 152 | 153 | NS_DURING 154 | { 155 | image = [[NSImage alloc] initWithContentsOfFile: path]; 156 | } 157 | NS_HANDLER 158 | { 159 | NSString *message = [localException reason]; 160 | NSRunAlertPanel(_(@"Problem loading theme icon image"), 161 | message, nil, nil, nil); 162 | } 163 | NS_ENDHANDLER 164 | if (image != nil) 165 | { 166 | NSSize s = [image size]; 167 | float scale = 1.0; 168 | 169 | if (s.height > 48.0) 170 | scale = 48.0 / s.height; 171 | if (48.0 / s.width < scale) 172 | scale = 48.0 / s.width; 173 | if (scale != 1.0) 174 | { 175 | [image setScalesWhenResized: YES]; 176 | s.height *= scale; 177 | s.width *= scale; 178 | [image setSize: s]; 179 | } 180 | [doc setResource: path forKey: @"GSThemeIcon"]; 181 | [iconView setImage: image]; 182 | RELEASE(image); 183 | } 184 | } 185 | } 186 | 187 | - (void) textDidEndEditing: (NSNotification*)aNotification 188 | { 189 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 190 | NSTextView *sender = [aNotification object]; 191 | NSString *s = [[sender string] stringByTrimmingSpaces]; 192 | 193 | // NSLog(@"End editing %@", aNotification); 194 | if (sender == details) 195 | { 196 | [doc setInfo: s forKey: @"GSThemeDetails"]; 197 | } 198 | else if (sender == license) 199 | { 200 | [doc setInfo: s forKey: @"GSThemeLicense"]; 201 | } 202 | else if (sender == authors) 203 | { 204 | NSMutableArray *a; 205 | unsigned count; 206 | 207 | a = [[s componentsSeparatedByString: @"\n"] mutableCopy]; 208 | count = [a count]; 209 | while (count-- > 0) 210 | { 211 | NSString *line = [a objectAtIndex: count]; 212 | 213 | if ([[line stringByTrimmingSpaces] length] == 0) 214 | { 215 | [a removeObjectAtIndex: count]; 216 | } 217 | } 218 | [doc setInfo: a forKey: @"GSThemeAuthors"]; 219 | RELEASE(a); 220 | } 221 | } 222 | 223 | - (NSString*) title 224 | { 225 | return @"Miscellaneous"; 226 | } 227 | @end 228 | 229 | -------------------------------------------------------------------------------- /PreviewElement.h: -------------------------------------------------------------------------------- 1 | /* PreviewElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "ThemeElement.h" 28 | 29 | @interface PreviewElement : ThemeElement 30 | { 31 | id previewView; 32 | id previewImage; 33 | } 34 | - (void) setPreview: (id)sender; 35 | - (void) takePreview: (id)sender; 36 | @end 37 | 38 | -------------------------------------------------------------------------------- /PreviewElement.m: -------------------------------------------------------------------------------- 1 | /* PreviewElement.m 2 | * 3 | * Copyright (C) 2006-2010 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import 28 | 29 | #import "AppController.h" 30 | #import "ThemeDocument.h" 31 | #import "PreviewElement.h" 32 | 33 | @implementation PreviewElement 34 | 35 | - (NSImage*) image 36 | { 37 | NSString *path; 38 | NSImage *image; 39 | 40 | image = nil; 41 | path = [[[GSTheme theme] infoDictionary] objectForKey: @"GSThemePreview"]; 42 | if (nil != path) 43 | { 44 | path = [[[GSTheme theme] bundle] pathForResource: path ofType: nil]; 45 | if (nil != path) 46 | { 47 | image = [[NSImage alloc] initWithContentsOfFile: path]; 48 | } 49 | } 50 | return [image autorelease]; 51 | } 52 | 53 | - (void) selectAt: (NSPoint)mouse 54 | { 55 | [previewImage setImage: [self image]]; 56 | [previewImage setNeedsDisplay]; 57 | [super selectAt: mouse]; 58 | } 59 | 60 | - (void) setPreview: (id)sender 61 | { 62 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 63 | NSImage *image = [sender image]; 64 | 65 | if (image != nil) 66 | { 67 | NSSize s = [image size]; 68 | float scale = 1.0; 69 | NSString *path = nil; 70 | 71 | if (s.height > 128.0) 72 | scale = 128.0 / s.height; 73 | if (128.0 / s.width < scale) 74 | scale = 128.0 / s.width; 75 | if (scale != 1.0) 76 | { 77 | [image setScalesWhenResized: YES]; 78 | s.height *= scale; 79 | s.width *= scale; 80 | [image setSize: s]; 81 | } 82 | // FIXME ... store image to a temporary file to copy into theme 83 | [doc setResource: path forKey: @"GSThemePreview"]; 84 | RELEASE(image); 85 | [previewImage setImage: [self image]]; 86 | } 87 | } 88 | 89 | - (void) takePreview: (id)sender 90 | { 91 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 92 | NSArray *fileTypes = [NSImage imageFileTypes]; 93 | NSOpenPanel *oPanel = [NSOpenPanel openPanel]; 94 | int result; 95 | 96 | [oPanel setAllowsMultipleSelection: NO]; 97 | [oPanel setCanChooseFiles: YES]; 98 | [oPanel setCanChooseDirectories: NO]; 99 | result = [oPanel runModalForDirectory: NSHomeDirectory() 100 | file: nil 101 | types: fileTypes]; 102 | if (result == NSOKButton) 103 | { 104 | NSString *path = [oPanel filename]; 105 | NSImage *image = nil; 106 | 107 | NS_DURING 108 | { 109 | image = [[NSImage alloc] initWithContentsOfFile: path]; 110 | } 111 | NS_HANDLER 112 | { 113 | NSString *message = [localException reason]; 114 | NSRunAlertPanel(_(@"Problem loading theme preview image"), 115 | message, nil, nil, nil); 116 | } 117 | NS_ENDHANDLER 118 | if (image != nil) 119 | { 120 | NSSize s = [image size]; 121 | float scale = 1.0; 122 | 123 | if (s.height > 128.0) 124 | scale = 128.0 / s.height; 125 | if (128.0 / s.width < scale) 126 | scale = 128.0 / s.width; 127 | if (scale != 1.0) 128 | { 129 | [image setScalesWhenResized: YES]; 130 | s.height *= scale; 131 | s.width *= scale; 132 | [image setSize: s]; 133 | } 134 | [doc setResource: path forKey: @"GSThemePreview"]; 135 | RELEASE(image); 136 | [previewImage setImage: [self image]]; 137 | } 138 | } 139 | } 140 | 141 | - (NSString*) title 142 | { 143 | return @"Preview"; 144 | } 145 | @end 146 | 147 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Thematic.app is a theme editor for GNUstep. 2 | 3 | Install and run Thematic.app, then read online help for details of 4 | what it can do. 5 | Alternatively, you can find the help file in Resources/ThematicHelp.rtf 6 | 7 | The remainder of this file is intended for people wishing to help improve 8 | Thematic.app itsself, rather than for people who merely with to use it to 9 | create themes. 10 | 11 | Theming has to be built into the GNUstep GUI in order for a theme editor 12 | to be useful ... this will be an incremental process, with capabilities 13 | being added to the editor as they are added to the gui library. 14 | 15 | To work on Thematic, you also need Gorm.app and ProjectCenter.app, 16 | and a copy of an rtf editor such as Ink.app if you wish to improve the 17 | online help (Resources/ThematicHelp.rtf). 18 | 19 | Building/using the current editor requires the *latest* version of 20 | the GUI from SVN. The major task in theming is now changing all the 21 | control drawing code to be themable ... identifying a minimal set of 22 | drawing methods for each control and defining the number of tile 23 | images needed for each, and updating the code in the GUI library. 24 | 25 | To help with developing Thematic itsself, we need to add code to deal 26 | with assigning tiles for particular controls and overriding theme drawing 27 | methods for particular controls. 28 | 29 | For most controls, this means: 30 | 1. Editing ThemeDocument.gorm to add the control to the main document window. 31 | 2. Modify ControlElement.m or implement a subclass of ControlElement to 32 | handle any special featurs needed for your control. 33 | If you create a subclass, this will probably also involve creating 34 | a new Gorm file for the inspector for the new control ... 35 | see ControlElement.gorm for an example. 36 | 3. Edit ThemeDocument.m to integrate the changes. 37 | 4. Define any tile images to be used to draw the control by editing 38 | Resources/CodeInfo.plist 39 | 5. Define any special colors to be used to draw the control by editing 40 | Resources/CodeInfo.plist 41 | 5. Define any NSInterfaceStyle values or defaults settings which control 42 | behavior fo the control by editing Resources/CodeInfo.plist 43 | 6. Define methods that can be overridden to draw the control differently ... 44 | 6a. Add the methods and a description of each to Resources/CodeInfo.plist 45 | 6b. Add template implementations for each method as a file whose name is 46 | Resources/xxx.txt where xxx is the method name with any colons replaced by 47 | underscores. 48 | 49 | 50 | TO DO 51 | 52 | We have more to do than just adding new controls to those we support. 53 | 54 | For one thing, attempting to design an even better iuser interface is always 55 | worthwhile. 56 | 57 | The current ability for Thematic.app to always reflect the current state of 58 | the theme under development is great, but it's not safe when you write code 59 | which can crass, and in crashing can crash Thematic.app 60 | It would be nice to come up with an alternative automatic mechanism for viewing the effects of changes which cannot crash Thematic itsself ... perhaps by 61 | running some other example application using NSTask? 62 | 63 | The code editor is currently glitchy ... which is strage since it's just 64 | a textview. This really needs to be improved, whether it's a case for 65 | changes in Thematic or fixes in the NSTextView class in the GUI library 66 | is not entirely clear. 67 | 68 | The code editor currently rebuilds the theme after each change ... which can be slow on a slow system. It would be better if, during an editing session, 69 | it kept the code in a subdirectory and only rebuilt the source for any 70 | methods actually changed. This should actually be quite easy to implement. 71 | 72 | -------------------------------------------------------------------------------- /Resources/CodeEditor.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | CodeEditor = { 4 | Actions = ( 5 | "codeDone:", 6 | "codeRevert:", 7 | "codeCancel:" 8 | ); 9 | Outlets = ( 10 | textView, 11 | panel 12 | ); 13 | Super = NSObject; 14 | }; 15 | FirstResponder = { 16 | Actions = ( 17 | "codeDone:", 18 | "codeRevert:", 19 | "codeCancel:" 20 | ); 21 | Super = NSObject; 22 | }; 23 | } -------------------------------------------------------------------------------- /Resources/CodeEditor.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/CodeEditor.gorm/data.info -------------------------------------------------------------------------------- /Resources/CodeEditor.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/CodeEditor.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/CodeInfo.plist: -------------------------------------------------------------------------------- 1 | /* This property list must be a dictionary defining the API for drawing 2 | * GUI controls. 3 | * At the top level it is keyed on control name ... which is the name of 4 | * the class of the control (or other GUI element). 5 | * Each control is defined by a dictionary containing various items. 6 | * An extra dictionary named 'Generic' contains extra theme information 7 | * not specific to particular controls. The code in CodeEditor.m must 8 | * deal with them specially. 9 | * 10 | * The keys are: 11 | * 12 | * ColorElements ... a dictionary listing the names of GUI elements 13 | * drawn as part of this control which are able to have a color set. 14 | * Each element listed is defined by a dictionary which may contain 15 | * an array keyed on 'States' listing the states for which colors 16 | * may be specified (Normal,Highlighted,Selected). If this dictionary 17 | * is missing, the 'Normal' state is assumed. 18 | * 19 | * Defaults ... a dictionary containing information about user defaults 20 | * settings which can be used for the control. Each item in the dictionary 21 | * identifies a particular setting. 22 | * 23 | * Fragments ... a dictionary mapping method names or generic names of 24 | * fragments of source, header or make files to help text describing 25 | * their use. For each of these listed fragments, a template file 26 | * must exist so that users have a starting poiint for editing the 27 | * fragment. 28 | * 29 | * TileElements ... a dictionary listing the names of GUI elements 30 | * drawn as part of this control and capable of being tiled. 31 | * Each element listed is defined by a dictionary which may contain 32 | * an array keyed on 'States' listing the states for which a tile image 33 | * may be specified (Normal,Highlighted,Selected). If this dictionary 34 | * is missing, the 'Normal' state is assumed. 35 | * 36 | */ 37 | { 38 | Generic = { 39 | Fragments = { 40 | CommonMethods = 41 | "This code fragment is provided to allow you to override methods wich are common to all of your theme rather than specific to a particular control (eg initialisation and deallocation."; 42 | IncludeHeaders = 43 | "This code fragment is provided to allow you to specify additional header files to be included at the stat of your theme code."; 44 | MakeAdditions = 45 | "This allows you to provide a makefile fragment to tell gnustep-make to link your theme with extra libraries or compile it with extra flags."; 46 | VariableDeclarations = 47 | "This code fragment allows you to declare extra instance variables for use by all your theme code."; 48 | }; 49 | }; 50 | NSButton = { 51 | ColorElements = { 52 | NSButton = { 53 | States = (Normal, Highlighted, Selected, Disabled); 54 | }; 55 | }; 56 | Fragments = { 57 | "drawButton:in:view:style:state:" = 58 | "Draws a button frame and background (not its content) for the specified cell and view."; 59 | }; 60 | TileElements = { 61 | NSButton = { 62 | States = (Normal, Highlighted, Selected, Disabled); 63 | }; 64 | }; 65 | }; 66 | NSMenuItem = { 67 | ColorElements = { 68 | NSMenuItem = { 69 | States = (Normal, Highlighted, Selected); 70 | }; 71 | }; 72 | Defaults = { 73 | }; 74 | Fragments = { 75 | "drawBorderAndBackgroundForMenuItemCell:withFrame:inView:state:isHorizontal:" = "Draws a border and background (not its content) for the specified cell and view. The flag says whether the menu is horizontal or not."; 76 | }; 77 | TileElements = { 78 | NSMenuItem = { 79 | States = (Normal, Highlighted, Selected); 80 | }; 81 | }; 82 | }; 83 | NSScroller = { 84 | ColorElements = { 85 | GSScrollerLeftArrow = {}; 86 | GSScrollerRightArrow = {}; 87 | GSScrollerUpArrow = {}; 88 | GSScrollerDownArrow = {}; 89 | GSScrollerHorizontalKnob = {}; 90 | GSScrollerVerticalKnob = {}; 91 | GSScrollerHorizontalSlot = {}; 92 | GSScrollerVerticalSlot = {}; 93 | }; 94 | Defaults = { 95 | "Arrows behavior" = { 96 | Name = NSScrollerInterfaceStyle; 97 | Description = "This controls the positioning of the arrow buttons within the scroller and also the behavior when you click on the scroller outside the arrows."; 98 | DefaultOption = NSNextStepInterfaceStyle; 99 | Options = { 100 | "Arrows at opposite ends of scroller" 101 | = NSWindows95InterfaceStyle; 102 | "Arrows at the same end of the scroller" 103 | = NSNextStepInterfaceStyle; 104 | }; 105 | }; 106 | "Buttons offset" = { 107 | Name = GSScrollerButtonsOffset; 108 | Description = "This controls the offset between the scroller slot border and the buttons within the slot."; 109 | DefaultOption = 1.0; 110 | Options = { 111 | "No offset between buttons and border" = 0.0; 112 | "Single pixel offset between buttons and border" = 1.0; 113 | "Double pixel offset between buttons and border" = 2.0; 114 | }; 115 | }; 116 | }; 117 | Fragments = { 118 | "cellForScrollerArrow:horizontal:" = 119 | "Returns the button cell used to draw a scroller arrow."; 120 | "cellForScrollerKnob:" = 121 | "Returns the button cell used to draw a scroller knob."; 122 | "cellForScrollerKnobSlot:" = 123 | "Returns the button cell used to draw a scroller knob slot."; 124 | "defaultScrollerWidth" = 125 | "Returns the scroller width to be used."; 126 | }; 127 | TileElements = { 128 | GSScrollerLeftArrow = {}; 129 | GSScrollerRightArrow = {}; 130 | GSScrollerUpArrow = {}; 131 | GSScrollerDownArrow = {}; 132 | GSScrollerHorizontalKnob = {}; 133 | GSScrollerVerticalKnob = {}; 134 | GSScrollerHorizontalSlot = {}; 135 | GSScrollerVerticalSlot = {}; 136 | }; 137 | }; 138 | NSScrollView = { 139 | ColorElements = { 140 | NSScrollView = {}; 141 | }; 142 | Defaults = { 143 | "Scroller position" = { 144 | Name = NSScrollViewInterfaceStyle; 145 | Description = "This controls the positioning of the vertical scroller within the scroll view."; 146 | DefaultOption = NSNextStepInterfaceStyle; 147 | Options = { 148 | "Scroller on right of view" 149 | = NSWindows95InterfaceStyle; 150 | "Scroller on left of view" 151 | = NSNextStepInterfaceStyle; 152 | }; 153 | }; 154 | }; 155 | Fragments = { 156 | }; 157 | TileElements = { 158 | }; 159 | }; 160 | } 161 | -------------------------------------------------------------------------------- /Resources/ColorElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | AppController = { 4 | Actions = ( 5 | "newDocument:", 6 | "openInspector:", 7 | "showPrefPanel:" 8 | ); 9 | Outlets = ( 10 | inspector 11 | ); 12 | Super = NSObject; 13 | }; 14 | ColorElement = { 15 | Actions = ( 16 | "takeNameFrom:" 17 | ); 18 | Outlets = ( 19 | colorMenu, 20 | colorWell 21 | ); 22 | Super = ThemeElement; 23 | }; 24 | FirstResponder = { 25 | Actions = ( 26 | "openInspector:", 27 | "showPrefPanel:", 28 | "takeColorFrom:", 29 | "takeNameFrom:" 30 | ); 31 | Super = NSObject; 32 | }; 33 | ThemeElement = { 34 | Actions = ( 35 | "takeColorFrom:" 36 | ); 37 | Outlets = ( 38 | window 39 | ); 40 | Super = NSObject; 41 | }; 42 | } -------------------------------------------------------------------------------- /Resources/ColorElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ColorElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/ColorElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ColorElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/CommonMethods.txt: -------------------------------------------------------------------------------- 1 | /* Use this to override methods of the GSTheme class below. 2 | * You may also add entirely new methods here. 3 | */ 4 | 5 | /* 6 | - (Class) colorClass 7 | { 8 | [super colorClass]; 9 | } 10 | */ 11 | 12 | /* 13 | - (void) dealloc 14 | { 15 | [super dealloc]; 16 | } 17 | */ 18 | 19 | /* 20 | - (Class) imageClass 21 | { 22 | [super imageClass]; 23 | } 24 | */ 25 | 26 | /* 27 | - (id) initWithBundle: (NSBundle*)myBundle 28 | { 29 | self = [super initWithBundle: myBundle]; 30 | return self; 31 | } 32 | */ 33 | -------------------------------------------------------------------------------- /Resources/ControlElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | ControlElement = { 4 | Actions = ( 5 | "takeCodeDelete:", 6 | "takeCodeEdit:", 7 | "takeCodeMethod:", 8 | "takeColorName:", 9 | "takeColorValue:", 10 | "takeDefsName:", 11 | "takeDefsValue:", 12 | "takeTileImage:", 13 | "takeTilePosition:", 14 | "takeTileStyle:", 15 | "takeTileDelete:", 16 | "takeColorDelete:", 17 | "takeTileName:" 18 | ); 19 | Outlets = ( 20 | codeDescription, 21 | codeMenu, 22 | colorsMenu, 23 | colorsWell, 24 | defsDescription, 25 | defsMenu, 26 | defsOption, 27 | tilesHorizontal, 28 | tilesImages, 29 | tilesMenu, 30 | tilesStyle, 31 | tilesVertical, 32 | colorsState, 33 | tilesState, 34 | tilesPreview 35 | ); 36 | Super = ThemeElement; 37 | }; 38 | FirstResponder = { 39 | Actions = ( 40 | "takeTileDelete:", 41 | "takeCodeDelete:", 42 | "takeCodeEdit:", 43 | "takeCodeMethod:", 44 | "takeColorDelete:", 45 | "takeColorName:", 46 | "takeColorValue:", 47 | "takeDefsName:", 48 | "takeDefsValue:", 49 | "takeTileImage:", 50 | "takeTileName:", 51 | "takeTilePosition:", 52 | "takeTileStyle:" 53 | ); 54 | Super = NSObject; 55 | }; 56 | ThemeElement = { 57 | Actions = ( 58 | ); 59 | Outlets = ( 60 | window 61 | ); 62 | Super = NSObject; 63 | }; 64 | } -------------------------------------------------------------------------------- /Resources/ControlElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ControlElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/ControlElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ControlElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/ImageAdd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ImageAdd.png -------------------------------------------------------------------------------- /Resources/ImageElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | FirstResponder = { 4 | Actions = ( 5 | "deleteImage:", 6 | "importImage:", 7 | "switchCollection:" 8 | ); 9 | Super = NSObject; 10 | }; 11 | ImageElement = { 12 | Actions = ( 13 | "deleteImage:", 14 | "importImage:", 15 | "switchCollection:" 16 | ); 17 | Outlets = ( 18 | scrollView, 19 | description, 20 | deleteButton, 21 | importButton, 22 | collectionMenu 23 | ); 24 | Super = ThemeElement; 25 | }; 26 | ThemeElement = { 27 | Actions = ( 28 | ); 29 | Outlets = ( 30 | window 31 | ); 32 | Super = NSObject; 33 | }; 34 | } -------------------------------------------------------------------------------- /Resources/ImageElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ImageElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/ImageElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ImageElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/IncludeHeaders.txt: -------------------------------------------------------------------------------- 1 | /* Add extra #include and #import lines for external headers used by your 2 | * theme code. 3 | * You may also place any code here which should be included in all your 4 | * theme code ... global declarations and macro definitions for instance. 5 | */ 6 | -------------------------------------------------------------------------------- /Resources/MakeAdditions.txt: -------------------------------------------------------------------------------- 1 | # eg -I/usr/include 2 | ADDITIONAL_INCLUDE_DIRS+= 3 | 4 | # eg -L/usr/lib 5 | ADDITIONAL_LIB_DIRS+= 6 | 7 | # eg. -lfoo 8 | Theme_BUNDLE_LIBS+= 9 | 10 | -------------------------------------------------------------------------------- /Resources/MenusElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | FirstResponder = { 4 | Actions = ( 5 | "takeBarTitleColorFrom:", 6 | "takeArrowImageFrom:", 7 | "takeBarColorFrom:", 8 | "takeMenuStyleFrom:" 9 | ); 10 | Super = NSObject; 11 | }; 12 | MenusElement = { 13 | Actions = ( 14 | "takeMenuStyleFrom:", 15 | "takeArrowImageFrom:", 16 | "takeBarTitleColorFrom:", 17 | "takeBarColorFrom:" 18 | ); 19 | Outlets = ( 20 | popup, 21 | arrowButton, 22 | barColorWell, 23 | barTitleColorWell 24 | ); 25 | Super = ThemeElement; 26 | }; 27 | ThemeElement = { 28 | Actions = ( 29 | ); 30 | Outlets = ( 31 | window 32 | ); 33 | Super = NSObject; 34 | }; 35 | } -------------------------------------------------------------------------------- /Resources/MenusElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/MenusElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/MenusElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/MenusElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/MiscElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | FirstResponder = { 4 | Actions = ( 5 | "newVersion:", 6 | "takeAuthor:", 7 | "takeDetails:", 8 | "takeIcon:" 9 | ); 10 | Super = NSObject; 11 | }; 12 | MiscElement = { 13 | Actions = ( 14 | "takeIcon:", 15 | "newVersion:" 16 | ); 17 | Outlets = ( 18 | iconView, 19 | authors, 20 | details, 21 | themeName, 22 | themeVersion, 23 | license 24 | ); 25 | Super = ThemeElement; 26 | }; 27 | ThemeElement = { 28 | Actions = ( 29 | ); 30 | Outlets = ( 31 | window 32 | ); 33 | Super = NSObject; 34 | }; 35 | } -------------------------------------------------------------------------------- /Resources/MiscElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/MiscElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/MiscElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/MiscElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/PreviewElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | FirstResponder = { 4 | Actions = ( 5 | "setPreview:", 6 | "takeMenuStyleFrom:", 7 | "takePreview:" 8 | ); 9 | Super = NSObject; 10 | }; 11 | PreviewElement = { 12 | Actions = ( 13 | "setPreview:", 14 | "takePreview:" 15 | ); 16 | Outlets = ( 17 | previewView, 18 | previewImage 19 | ); 20 | Super = ThemeElement; 21 | }; 22 | ThemeElement = { 23 | Actions = ( 24 | ); 25 | Outlets = ( 26 | window 27 | ); 28 | Super = NSObject; 29 | }; 30 | } -------------------------------------------------------------------------------- /Resources/PreviewElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/PreviewElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/PreviewElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/PreviewElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/Thematic.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | AppController = { 4 | Actions = ( 5 | "newDocument:", 6 | "openColorsInspector:", 7 | "openImagesInspector:", 8 | "showPrefPanel:" 9 | ); 10 | Outlets = ( 11 | colorsInspector, 12 | imagesInspector 13 | ); 14 | Super = NSObject; 15 | }; 16 | FirstResponder = { 17 | Actions = ( 18 | "openColorsInspector:", 19 | "openImagesInspector:", 20 | "orderFrontFontPanel:", 21 | "showPrefPanel:" 22 | ); 23 | Super = NSObject; 24 | }; 25 | } -------------------------------------------------------------------------------- /Resources/Thematic.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/Thematic.gorm/data.info -------------------------------------------------------------------------------- /Resources/Thematic.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/Thematic.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/Thematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/Thematic.png -------------------------------------------------------------------------------- /Resources/ThematicHelp.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg10000\cocoartf102{\fonttbl\f0\fnil Bitstream Vera Sans;} 2 | {\colortbl;\red0\green0\blue0;} 3 | \f0\fs24\pard\tx0\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\ql \uc0 This is a theme editor for GNUstep. It is at an early \cf1 \uc0 but usable \cf0 \uc0 stage of development ...\cf0\cf1 \uc0 \par 4 | \par 5 | The design of the editor is that any theme changes should take effect immediately and be applied to the running application so that you can effectively preview them. For instance, if you write code overriding the drawing of a button, Thematic immediately builds that code, and loads the new theme so that you can see its effects. Similarly, of you change the control text color, all the control text in Thematic immediately changes color.\par 6 | Unfortunately, due to current limitations in the GUI/backend, changes to whether windows are decorated natively or not do not take effect until the application using the them is restarted :-(\par 7 | \cf0 \uc0 \par 8 | Theming has to be built into the GNUstep GUI in order for a theme editor to be useful, and this will be an incremental process, with capabilities being added to the editor as they are added to the GUI library. \par 9 | \par 10 | Building\cf0\cf1 \uc0 /using\cf0 \uc0 the theme editor \cf0\cf1 \uc0 generally \cf0 \uc0 requires the *latest* version of the GUI from SVN.\par 11 | \par 12 | \fs26 \uc0 Current capabilities are as follows:\par 13 | \fs24 \uc0 \par 14 | 1. Control of system colors\par 15 | Click on the color wheel icon in the main theme window to raise an inspector which permits you to redefine all the system colors used in drawing controls in the GUI.\par 16 | \par 17 | 2. Control of system images\par 18 | \cf0\cf1 \uc0 Click on the images icon in the main theme window to raise an inspector which permits you to redefine all the system images used in drawing controls in the GUI.\par 19 | \par 20 | 3. Control of menus\par 21 | Click on the menus icon to raise an inspector allowing you to change menu style.\par 22 | In future this should allow detailed control over how menus are drawn.\par 23 | \par 24 | 4. Control of windows and panels\par 25 | Click on the windows icon to raise an inspector allowing you to change whether window decorations are handled by the GUI (themed) or drawn natively by the backend.\par 26 | In future this should allow detailed control over how window decorations are drawn.\par 27 | \par 28 | 5. General/miscellaneous settings\par 29 | Click on the GNUstep logo to set attributes for the theme being edited/created ...\par 30 | The authorship, the icon to identify the theme etc.\par 31 | \par 32 | 6. Drawing controls by tiling images\par 33 | Clicking on a control in the main theme window raises a tabbed inspector where the \rquote Tiles\rquote tab allows you to define the image to be tiled to draw that control and the portions of the image to use for different purposes when tiling. The image for a control is split into nine sections producing four corner sections drawn directly, and the intermediary sections which are repeatedly tiled to fill the actual size of the control.\par 34 | \par 35 | 7. Specifying colors for a control and its subsidiary controls\par 36 | Clicking on a control in the main theme window raises a tabbed inspector where the \rquote Colors\rquote tab allows you to define the colors used to draw the control.\par 37 | \par 38 | 8. Specifying options for behavior of a control and its subsidiary controls\par 39 | Clicking on a control in the main theme window raises a tabbed inspector where the \rquote Options\rquote tab allows you to define any options used to control the behavior of the control.\par 40 | \par 41 | 9. Implementing new methods to draw controls\par 42 | Clicking on a control in the main theme window raises a tabbed inspector where the \rquote Code\rquote tab allows you to select the drawingpi methods used to draw that control and edit code to subclass those methods (or delete the subclassed version of a method).\par 43 | \par 44 | It is possible to combine all these mechanisms freely ... for instance by overriding the drawing method, calling the superclass implementation (which draws a background in a specified colour and tiles images to form a border) then draw extra decoration on top of that.\par 45 | \par 46 | Much of the theme functionality is implemented by adjusting values in the user defaults system. This is carefully done so that the defaults set by a theme will be overridden by any defaults set explicitly for an application. It is thus possible to use a theme but tweak its exact behavior for a particular application.\par 47 | \par 48 | Using a theme is easy ... to make a theme available, the theme bundle itsself simply needs to be copied into either your system-wide Themes directory or your own personal one (usually GNUstep/Library/Themes in your home directory). Thematic normally edits themes in your personal theme directory.\par 49 | \par 50 | If a theme is available then you can set it using the user defaults system to set the GSTheme key to have the theme\rquote s name as its value\par 51 | (eg. \rquote defaults write NSGlobalDomain GSTheme MyTheme\rquote ). \par 52 | However an easier way to set the theme for an individual application (if that application has a standard info panel) is to use the application menu to open the Info panel, then click on the name of the current theme to raise the theme selection panel.\par 53 | \par 54 | \par 55 | } -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/MenusPalette.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/MenusPalette.tiff -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | ThemeDocument = { 4 | Actions = ( 5 | "saveDocument:", 6 | "saveDocumentAs:", 7 | "saveDocumentTo:" 8 | ); 9 | Outlets = ( 10 | window, 11 | colorsView, 12 | imagesView, 13 | menusView, 14 | windowsView, 15 | extraView, 16 | "_inspector", 17 | previewView, 18 | menuItemView 19 | ); 20 | Super = NSObject; 21 | }; 22 | } -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/data.info -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/themeColors.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/themeColors.tiff -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/themeImages.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/themeImages.tiff -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/themeMenu.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/themeMenu.tiff -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/themeMisc.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/themeMisc.tiff -------------------------------------------------------------------------------- /Resources/ThemeDocument.gorm/themeWindow.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeDocument.gorm/themeWindow.tiff -------------------------------------------------------------------------------- /Resources/ThemeInspector.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | AppController = { 4 | Actions = ( 5 | "newDocument:", 6 | "openInspector:", 7 | "showPrefPanel:" 8 | ); 9 | Outlets = ( 10 | inspector 11 | ); 12 | Super = NSObject; 13 | }; 14 | FirstResponder = { 15 | Actions = ( 16 | "openInspector:", 17 | "showPrefPanel:" 18 | ); 19 | Super = NSObject; 20 | }; 21 | } -------------------------------------------------------------------------------- /Resources/ThemeInspector.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeInspector.gorm/data.info -------------------------------------------------------------------------------- /Resources/ThemeInspector.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/ThemeInspector.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/VariableDeclarations.txt: -------------------------------------------------------------------------------- 1 | { 2 | /* Declare additional instance variables for your theme here */ 3 | } 4 | -------------------------------------------------------------------------------- /Resources/WindowsElement.gorm/data.classes: -------------------------------------------------------------------------------- 1 | { 2 | "## Comment" = "Do NOT change this file, Gorm maintains it"; 3 | FirstResponder = { 4 | Actions = ( 5 | "takeWindowStyleFrom:" 6 | ); 7 | Super = NSObject; 8 | }; 9 | ThemeElement = { 10 | Actions = ( 11 | ); 12 | Outlets = ( 13 | window 14 | ); 15 | Super = NSObject; 16 | }; 17 | WindowsElement = { 18 | Actions = ( 19 | "takeWindowStyleFrom:" 20 | ); 21 | Outlets = ( 22 | popup 23 | ); 24 | Super = ThemeElement; 25 | }; 26 | } -------------------------------------------------------------------------------- /Resources/WindowsElement.gorm/data.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/WindowsElement.gorm/data.info -------------------------------------------------------------------------------- /Resources/WindowsElement.gorm/objects.gorm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Resources/WindowsElement.gorm/objects.gorm -------------------------------------------------------------------------------- /Resources/drawBorderAndBackgroundForMenuItemCell_withFrame_inView_state_isHorizontal_.txt: -------------------------------------------------------------------------------- 1 | - (void) drawBorderAndBackgroundForMenuItemCell: (NSMenuItemCell *)cell 2 | withFrame: (NSRect)cellFrame 3 | inView: (NSView *)controlView 4 | state: (GSThemeControlState)state 5 | isHorizontal: (BOOL)isHorizontal 6 | { 7 | [self drawBorderAndBackgroundForMenuItemCell: cell 8 | withFrame: cellFrame 9 | inView: controlView 10 | state: state 11 | isHorizontal: isHorizontal]; 12 | } 13 | -------------------------------------------------------------------------------- /Resources/drawButton_in_view_style_state_.txt: -------------------------------------------------------------------------------- 1 | - (void) drawButton: (NSRect)frame 2 | in: (NSCell*)cell 3 | view: (NSView*)view 4 | style: (int)style 5 | state: (GSThemeControlState)state 6 | { 7 | [super drawButton: frame 8 | in: cell 9 | view: view 10 | style: style 11 | state: state]; 12 | } 13 | -------------------------------------------------------------------------------- /Thematic.pcproj/PC.project: -------------------------------------------------------------------------------- 1 | { 2 | APPLICATIONICON = "Thematic.png"; 3 | "APP_DOCUMENT_BASED" = NO; 4 | "APP_TYPE" = GORM; 5 | "BUILDER_ARGS" = ( 6 | ); 7 | "BUILDER_TARGETS" = ( 8 | all, 9 | install, 10 | uninstall, 11 | clean, 12 | distclean, 13 | dist 14 | ); 15 | "BUILDER_VERBOSE" = YES; 16 | "BUNDLE_IDENTIFIER" = "org.gnustep.Thematic"; 17 | BuildTarget = Debug; 18 | BuildTargetArgs = ""; 19 | "CLASS_FILES" = ( 20 | "AppController.m", 21 | "ThemeDocument.m", 22 | "ThemeElement.m", 23 | "ImageElement.m", 24 | "MenusElement.m", 25 | "WindowsElement.m", 26 | "MiscElement.m", 27 | "ControlElement.m", 28 | "ColorElement.m", 29 | "TilesBox.m", 30 | "CodeEditor.m", 31 | "MenuItemElement.m", 32 | "PreviewElement.m" 33 | ); 34 | COMPILEROPTIONS = ""; 35 | CPPOPTIONS = ""; 36 | "CREATION_DATE" = "2006-09-18 14:00:14 +0100"; 37 | "DOCU_FILES" = ( 38 | "ThematicHelp.rtf" 39 | ); 40 | FRAMEWORKS = ( 41 | ); 42 | "HEADER_FILES" = ( 43 | "AppController.h", 44 | "ThemeDocument.h", 45 | "ThemeElement.h", 46 | "ColorElement.h", 47 | "ImageElement.h", 48 | "MenusElement.h", 49 | "WindowsElement.h", 50 | "MiscElement.h", 51 | "ControlElement.h", 52 | "TilesBox.h", 53 | "CodeEditor.h", 54 | "MenuItemElement.h", 55 | "PreviewElement.h" 56 | ); 57 | "HELP_FILE" = "ThematicHelp.rtf"; 58 | IMAGES = ( 59 | "Thematic.png" 60 | ); 61 | INSTALLDIR = "$(HOME)/GNUstep"; 62 | INSTALLDOMAIN = System; 63 | INTERFACES = ( 64 | "Thematic.gorm", 65 | "ThemeInspector.gorm", 66 | "ColorElement.gorm", 67 | "ThemeDocument.gorm", 68 | "ImageElement.gorm", 69 | "WindowsElement.gorm", 70 | "MenusElement.gorm", 71 | "MiscElement.gorm", 72 | "ControlElement.gorm", 73 | "CodeEditor.gorm" 74 | ); 75 | LANGUAGE = English; 76 | LIBRARIES = ( 77 | "gnustep-base", 78 | "gnustep-gui" 79 | ); 80 | LINKEROPTIONS = ""; 81 | "LOCALIZED_RESOURCES" = ( 82 | ); 83 | MAININTERFACE = "Thematic.gorm"; 84 | MAKEFILEDIR = "$(GNUSTEP_MAKEFILES)"; 85 | "OBJC_COMPILEROPTIONS" = ""; 86 | "OTHER_RESOURCES" = ( 87 | "CodeInfo.plist", 88 | "drawButton_in_view_style_state_.txt", 89 | "CommonMethods.txt", 90 | "IncludeHeaders.txt", 91 | "MakeAdditions.txt", 92 | "VariableDeclarations.txt" 93 | ); 94 | "OTHER_SOURCES" = ( 95 | "main.m" 96 | ); 97 | "PRINCIPAL_CLASS" = NSApplication; 98 | "PROJECT_AUTHORS" = ( 99 | "Richard Frith-MacDonald", 100 | "Riccardo Mottola" 101 | ); 102 | "PROJECT_COPYRIGHT" = "Copyright (C) 2006-2021"; 103 | "PROJECT_COPYRIGHT_DESC" = "Released under GPL3"; 104 | "PROJECT_CREATOR" = "richard,,,"; 105 | "PROJECT_DESCRIPTION" = "The Theme editor for GNUstep"; 106 | "PROJECT_DOCUMENTTYPES" = ( 107 | { 108 | NSIcon = "Thematic.png"; 109 | NSUnixExtensions = ( 110 | theme 111 | ); 112 | } 113 | ); 114 | "PROJECT_GROUP" = "No group avaliable!"; 115 | "PROJECT_MAINTAINER" = "richard,,,"; 116 | "PROJECT_NAME" = Thematic; 117 | "PROJECT_RELEASE" = "0.2"; 118 | "PROJECT_SUMMARY" = "No summary avaliable!"; 119 | "PROJECT_TYPE" = Application; 120 | "PROJECT_URL" = ""; 121 | "SEARCH_HEADER_DIRS" = ( 122 | ); 123 | "SEARCH_LIB_DIRS" = ( 124 | ); 125 | SUBPROJECTS = ( 126 | ); 127 | "SUPPORTING_FILES" = ( 128 | "ThematicInfo.plist" 129 | ); 130 | "USER_LANGUAGES" = ( 131 | AmericanEnglish, 132 | English 133 | ); 134 | } -------------------------------------------------------------------------------- /Thematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnustep/apps-thematic/a8e0ca7dc5fa5917ba6a447edda29e8f2c091bbf/Thematic.png -------------------------------------------------------------------------------- /ThematicInfo.plist: -------------------------------------------------------------------------------- 1 | { 2 | ApplicationDescription = "The Theme editor for GNUstep"; 3 | ApplicationIcon = "Thematic.png"; 4 | ApplicationName = Thematic; 5 | ApplicationRelease = "0.2"; 6 | Authors = ( 7 | "Richard Frith-MacDonald", 8 | "Riccardo Mottola" 9 | ); 10 | CFBundleIdentifier = "org.gnustep.Thematic"; 11 | Copyright = "Copyright (C) 2006-2021"; 12 | CopyrightDescription = "Released under GPL3"; 13 | FullVersionID = "0.2"; 14 | GSHelpContentsFile = "ThematicHelp.rtf"; 15 | NSExecutable = Thematic; 16 | NSIcon = "Thematic.png"; 17 | NSMainNibFile = "Thematic.gorm"; 18 | NSPrincipalClass = NSApplication; 19 | NSRole = Application; 20 | NSTypes = ( 21 | { 22 | NSIcon = "Thematic.png"; 23 | NSUnixExtensions = ( 24 | theme 25 | ); 26 | } 27 | ); 28 | } -------------------------------------------------------------------------------- /ThemeDocument.h: -------------------------------------------------------------------------------- 1 | /* ThemeDocument.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import 28 | 29 | @class NSColor; 30 | @class NSColorList; 31 | @class NSDictionary; 32 | @class NSNotification; 33 | @class NSString; 34 | @class NSView; 35 | @class NSWindow; 36 | @class ThemeDocumentView; 37 | @class ThemeElement; 38 | 39 | /** 40 | *

This works in conjunction with a window and the inspector panel to 41 | * manage loading, saving, and editing of a theme document.
42 | * A theme document is a bundle containing the theme resources and 43 | * (perhaps) a loadable binary ... when we support it. 44 | *

45 | *

Basically, the idea of the user interface is that the document window 46 | * provides a few icons you can click on to raise an inspector for editing. 47 | *

48 | * 49 | * System colors 50 | * System images 51 | * Menu settings 52 | * Window settings 53 | * 54 | *

Everything else in the document window is a GUI element (NSControl) 55 | * and clicking on one of the elements should select it and activate the 56 | * inspector for it, which should let you change any NSInterfaceStyle keys for 57 | * the element and let you set an image/images for tiling over the rectangle 58 | * to draw it. 59 | *

60 | *

For more complex GUI elements, it should be possible to click inside 61 | * the selected element to select a subsidiary element within int, and provide 62 | * theme info for that (eg. the knob inside a scroller). 63 | *

64 | *

Any action to change part of the theme configuration should be 65 | * immediately made visible by changing the running application to effectively 66 | * use the modified theme. 67 | *

68 | */ 69 | @interface ThemeDocument : NSObject 70 | { 71 | id window; // Not retained 72 | id colorsView; // Not retained 73 | id imagesView; // Not retained 74 | id menusView; // Not retained 75 | id windowsView; // Not retained 76 | id extraView; // Not retained 77 | id previewView; // Not retained 78 | id menuItemView; // Not retained 79 | id _inspector; // Not retained 80 | ThemeElement *_selected; // Not retained 81 | NSPoint _selectionPoint; 82 | NSMutableDictionary *_info; 83 | NSMutableDictionary *_defs; // Not retained 84 | NSMutableDictionary *_modified; 85 | NSMutableArray *_elements; 86 | NSColorList *_colors; 87 | NSColorList *_extraColors[GSThemeSelectedState+1]; 88 | NSString *_name; 89 | NSString *_path; 90 | NSString *_work; 91 | NSString *_rsrc; 92 | NSString *_build; 93 | GSTheme *_theme; 94 | } 95 | 96 | /** Try to make the theme we are editing active for preview purposes. 97 | */ 98 | - (void) activate; 99 | 100 | /** Return a dictionary whose keys are application bundle identifiers 101 | * and whose values are arrays of image names for those applications. 102 | */ 103 | - (NSDictionary*) applicationImageNames; 104 | 105 | /** Returns the directory in which cod should be built. 106 | */ 107 | - (NSString*) buildDirectory; 108 | 109 | - (void) changeSelection: (NSView*)aView at: (NSPoint)mousePoint; 110 | 111 | /** Returns the code fragment for the specified key, or nil if none is 112 | * available. Places the last modifiecation date of the code in *since 113 | * if it is not zero. 114 | */ 115 | - (NSString*) codeForKey: (NSString*)key since: (NSDate**)since; 116 | 117 | - (NSColor*) colorForKey: (NSString*)aName; 118 | 119 | /** Returns the specified default string if one has been set for this 120 | * theme, nil otherwise. 121 | */ 122 | - (NSString*) defaultForKey: (NSString*)key; 123 | 124 | - (ThemeElement*) elementForView: (NSView*)aView; 125 | 126 | - (NSColor*) extraColorForKey: (NSString*)aName; 127 | 128 | - (NSImage*) imageForKey: (NSString*)aKey; 129 | 130 | /** 131 | * Returns the current info dictionary for the document. 132 | */ 133 | - (NSDictionary*) infoDictionary; 134 | 135 | - (id) initWithPath: (NSString*)path; 136 | 137 | - (NSString*) name; 138 | 139 | - (void) notified: (NSNotification*)n; 140 | 141 | /** 142 | * Return the path from which this theme was loaded or saved. 143 | */ 144 | - (NSString*) path; 145 | 146 | /** 147 | * Save to specified path. 148 | */ 149 | - (BOOL) saveToPath: (NSString*)path; 150 | 151 | - (void) saveDocument: (id)sender; 152 | - (void) saveDocumentAs: (id)sender; 153 | - (void) saveDocumentTo: (id)sender; 154 | 155 | /** 156 | * Returns the current selection in the main theme window. 157 | */ 158 | - (ThemeElement*) selected; 159 | 160 | /** 161 | * Copies the binary bundle into place after deleting any existing version. 162 | * If path is nil, this just deletes the existing binary bundle. 163 | */ 164 | - (void) setBinaryBundle: (NSString*)path; 165 | 166 | /** 167 | * Informs the document that a change has been made to a 168 | * code fragment whose name is key.
169 | * If the path is nil, this means that the code fragment 170 | * needs to be removed. 171 | */ 172 | - (void) setCode: (NSString*)path forKey: (NSString*)key; 173 | 174 | /** 175 | * Informs the document that a change has been made to a 176 | * system color whose name is key. 177 | */ 178 | - (void) setColor: (NSColor*)color forKey: (NSString*)key; 179 | 180 | /** 181 | * Informs the document that a change has been made to a user default 182 | * which should be associated with the theme. 183 | */ 184 | - (void) setDefault: (NSString*)value forKey: (NSString*)key; 185 | 186 | /** 187 | * Informs the document that a change has been made to a 188 | * extra color whose name is key. 189 | */ 190 | - (void) setExtraColor: (NSColor*)color forKey: (NSString*)key; 191 | 192 | /** 193 | * Informs the document that a change has been made to the image 194 | * whose name is key. The value of path is the location of the 195 | * file containing the new image. 196 | */ 197 | - (void) setImage: (NSString*)path forKey: (NSString*)key; 198 | 199 | /** 200 | * Informs the document that a change has been made to information 201 | * to be stored in Info-gnustep.plist. 202 | */ 203 | - (void) setInfo: (id)value forKey: (NSString*)key; 204 | 205 | /** 206 | * Set the path this document should be saved to, and change its window 207 | * title to match. 208 | */ 209 | - (void) setPath: (NSString*)path; 210 | 211 | /** 212 | * Asks the document to import a resource from the specified path. 213 | * The name of the resource will be the last component of the path 214 | * unless that would cause an existing resource to be overwritten. 215 | * The name will be stored in the Info-gnustep.plist file using key. 216 | */ 217 | - (void) setResource: (NSString*)path forKey: (NSString*)key; 218 | 219 | /** 220 | * Set the tiling image (from the image in the file at path) and 221 | * division points for the named tiles. 222 | */ 223 | - (void) setTiles: (NSString*)name 224 | withPath: (NSString*)path 225 | fillStyle: (NSString*)fill 226 | hDivision: (int)h 227 | vDivision: (int)v; 228 | 229 | /** Return the current testTheme being edited. 230 | */ 231 | - (GSTheme*) testTheme; 232 | 233 | /** 234 | * Return the tiling image (if known) and the division points for the 235 | * named tiles. 236 | */ 237 | - (NSImage*) tiles: (NSString*)name 238 | fillStyle: (NSString**)f 239 | hDivision: (int*)h 240 | vDivision: (int*)v; 241 | 242 | /** return current theme version. 243 | */ 244 | - (NSString*) versionIncrementMajor: (BOOL)major incrementMinor: (BOOL)minor; 245 | 246 | @end 247 | 248 | 249 | -------------------------------------------------------------------------------- /ThemeElement.h: -------------------------------------------------------------------------------- 1 | /* ThemeElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | 28 | @class NSMutableArray; 29 | @class NSView; 30 | @class ThemeDocument; 31 | 32 | @interface ThemeElement : NSObject 33 | { 34 | id window; 35 | NSView *inspector; 36 | NSView *view; // Not retained 37 | ThemeDocument *owner; // Not retained 38 | } 39 | /** Deselect the current element 40 | */ 41 | - (void) deselect; 42 | 43 | /** Return name for the Gorm file for this element 44 | */ 45 | - (NSString*) gormName; 46 | 47 | - (id) initWithView: (NSView*)aView 48 | owner: (ThemeDocument*)aDocument; 49 | 50 | /** Handle mouse click to select inspector for the view. 51 | */ 52 | - (void) selectAt: (NSPoint)mouse; 53 | 54 | /** Return the title for the inspector window. 55 | */ 56 | - (NSString*) title; 57 | 58 | /** Return the view this element is handling 59 | */ 60 | - (NSView*) view; 61 | @end 62 | 63 | -------------------------------------------------------------------------------- /ThemeElement.m: -------------------------------------------------------------------------------- 1 | /* ThemeElement.m 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeElement.h" 29 | 30 | @implementation ThemeElement 31 | 32 | - (void) dealloc 33 | { 34 | RELEASE(inspector); 35 | [super dealloc]; 36 | } 37 | 38 | - (void) deselect 39 | { 40 | NSView *v; 41 | 42 | v = [[[AppController sharedController] inspector] contentView]; 43 | if (v == inspector) 44 | { 45 | [[[AppController sharedController] inspector] setContentView: nil]; 46 | [window setContentView: v]; 47 | [[window contentView] setNeedsDisplay: YES]; 48 | } 49 | } 50 | 51 | - (NSString*) gormName 52 | { 53 | return NSStringFromClass(object_getClass(self)); 54 | } 55 | 56 | - (id) initWithView: (NSView*)aView 57 | owner: (ThemeDocument*)aDocument 58 | { 59 | view = aView; 60 | owner = aDocument; 61 | [NSBundle loadNibNamed: [self gormName] owner: self]; 62 | inspector = RETAIN([window contentView]); 63 | return self; 64 | } 65 | 66 | - (void) selectAt: (NSPoint)mouse 67 | { 68 | NSWindow *inspectorWindow; 69 | 70 | [window setContentView: nil]; 71 | inspectorWindow = [[AppController sharedController] inspector]; 72 | [inspectorWindow setContentView: inspector]; 73 | [[window contentView] setNeedsDisplay: YES]; 74 | [inspectorWindow setTitle: [NSString stringWithFormat: @"%@ Inspector", 75 | [self title]]]; 76 | [inspectorWindow orderFront: self]; 77 | } 78 | 79 | - (NSString*) title 80 | { 81 | if ([view isKindOfClass: [NSImageView class]] == YES) 82 | { 83 | return @"Theme"; 84 | } 85 | else 86 | { 87 | return NSStringFromClass([view class]); 88 | } 89 | } 90 | 91 | - (NSView*) view 92 | { 93 | return view; 94 | } 95 | @end 96 | 97 | -------------------------------------------------------------------------------- /TilesBox.h: -------------------------------------------------------------------------------- 1 | /* TilesBox.h 2 | * 3 | * Copyright (C) 2006-2008 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006,2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | @class ControlElement; 27 | 28 | @interface TilesBox : NSView 29 | { 30 | ControlElement *owner; 31 | } 32 | - (void) setOwner: (id)o; 33 | @end 34 | @interface FlippedTilesBox : TilesBox 35 | @end 36 | 37 | 38 | -------------------------------------------------------------------------------- /TilesBox.m: -------------------------------------------------------------------------------- 1 | /* TilesBox.m 2 | * 3 | * Copyright (C) 2006-2008 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006,2008 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeDocument.h" 29 | #import "ControlElement.h" 30 | #import "TilesBox.h" 31 | 32 | @implementation TilesBox 33 | 34 | - (void) drawRect: (NSRect)rect 35 | { 36 | GSDrawTiles *t; 37 | NSColor *b = [NSColor controlBackgroundColor]; 38 | NSString *n = [owner elementName]; 39 | 40 | if (n == nil) 41 | { 42 | t = nil; 43 | } 44 | else 45 | { 46 | t = [[GSTheme theme] tilesNamed: [owner elementName] 47 | state: [owner elementState]]; 48 | } 49 | if (t == nil) 50 | { 51 | NSRectFill([self bounds]); 52 | } 53 | else 54 | { 55 | t = [t copy]; 56 | if ([self superview] == [owner tilesPreview]) 57 | { 58 | [[GSTheme theme] fillRect: [self bounds] 59 | withTiles: t 60 | background: b 61 | fillStyle: [owner style]]; 62 | } 63 | else 64 | { 65 | [[GSTheme theme] fillRect: [self bounds] 66 | withTiles: t 67 | background: b 68 | fillStyle: GSThemeFillStyleMatrix]; 69 | } 70 | [t release]; 71 | } 72 | } 73 | 74 | - (void) mouseDown: (NSEvent*)anEvent 75 | { 76 | if ([self superview] == [owner tilesPreview]) 77 | { 78 | return; 79 | } 80 | [owner takeTileImage: self]; 81 | } 82 | 83 | - (void) setOwner: (id)o 84 | { 85 | owner = o; 86 | } 87 | @end 88 | 89 | @implementation FlippedTilesBox 90 | - (BOOL) isFlipped 91 | { 92 | return YES; 93 | } 94 | @end 95 | 96 | -------------------------------------------------------------------------------- /WindowsElement.h: -------------------------------------------------------------------------------- 1 | /* WindowsElement.h 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "ThemeElement.h" 28 | 29 | @interface WindowsElement : ThemeElement 30 | { 31 | id popup; 32 | } 33 | - (void) takeWindowStyleFrom: (id)sender; 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /WindowsElement.m: -------------------------------------------------------------------------------- 1 | /* WindowsElement.m 2 | * 3 | * Copyright (C) 2006 Free Software Foundation, Inc. 4 | * 5 | * Author: Richard Frith-Macdonald 6 | * Date: 2006 7 | * 8 | * This file is part of GNUstep. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | #import 27 | #import "AppController.h" 28 | #import "ThemeDocument.h" 29 | #import "WindowsElement.h" 30 | 31 | @implementation WindowsElement 32 | - (void) selectAt: (NSPoint)mouse 33 | { 34 | ThemeDocument *doc; 35 | NSString *val; 36 | 37 | doc = [[AppController sharedController] selectedDocument]; 38 | val = [doc defaultForKey: @"GSBackHandlesWindowDecorations"]; 39 | if (val != nil && [val boolValue] == NO) 40 | { 41 | [popup selectItemAtIndex: [popup indexOfItemWithTag: 1]]; 42 | } 43 | else 44 | { 45 | [popup selectItemAtIndex: [popup indexOfItemWithTag: 0]]; 46 | } 47 | [super selectAt: mouse]; 48 | } 49 | 50 | - (void) takeWindowStyleFrom: (id)sender 51 | { 52 | ThemeDocument *doc = [[AppController sharedController] selectedDocument]; 53 | int style = [[sender selectedItem] tag]; 54 | 55 | switch (style) 56 | { 57 | case 0: /* Natively */ 58 | [doc setDefault: @"YES" 59 | forKey: @"GSBackHandlesWindowDecorations"]; 60 | break; 61 | default: /* By theme */ 62 | [doc setDefault: @"NO" 63 | forKey: @"GSBackHandlesWindowDecorations"]; 64 | break; 65 | } 66 | } 67 | 68 | - (NSString*) title 69 | { 70 | return @"Windows"; 71 | } 72 | @end 73 | 74 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | /* 2 | Project: Thematic 3 | 4 | Copyright (C) 2006 Free Software Foundation 5 | 6 | Author: Richard Frith-MacDonald 7 | 8 | Created: 2006-09-18 14:00:14 +0100 by richard 9 | 10 | This application is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU General Public 12 | License as published by the Free Software Foundation; either 13 | version 2 of the License, or (at your option) any later version. 14 | 15 | This application is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Library General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. 23 | */ 24 | 25 | #import 26 | 27 | int 28 | main(int argc, const char *argv[]) 29 | { 30 | return NSApplicationMain (argc, argv); 31 | } 32 | 33 | --------------------------------------------------------------------------------