diff --git a/DBModeler/AdaptorsPanel.h b/DBModeler/AdaptorsPanel.h new file mode 100644 index 0000000..f029b67 --- /dev/null +++ b/DBModeler/AdaptorsPanel.h @@ -0,0 +1,48 @@ +#ifndef __AdaptorsPanel_H_ +#define __AdaptorsPanel_H_ + +/* + AdaptorsPanel.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include + + +@interface AdaptorsPanel : NSObject +{ + NSWindow *_window; + NSBrowser *brws_adaptors; + NSButton *btn_ok; + NSButton *btn_cancel; + NSBox *_box; + NSTextField *_label; +} + +-(NSString *)runAdaptorsPanel; + +@end + + +#endif // __AdaptorsPanel_H + diff --git a/DBModeler/AdaptorsPanel.m b/DBModeler/AdaptorsPanel.m new file mode 100644 index 0000000..fb861a2 --- /dev/null +++ b/DBModeler/AdaptorsPanel.m @@ -0,0 +1,144 @@ +/** + AdaptorsPanel.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include "AdaptorsPanel.h" +#include +static NSArray *_adaptorNames; + +@implementation AdaptorsPanel + +- (void) dealloc +{ + DESTROY(_window); + DESTROY(_adaptorNames); + /* released by window + _label + brws_adaptors + btn_ok + btn_cancel + */ + [super dealloc]; +} + +- (id) init +{ + if (self = [super init]) + { + _adaptorNames = RETAIN([EOAdaptor availableAdaptorNames]); + /* redo all these numbers so buttons and labels are on the right? */ + _window = [[NSWindow alloc] + initWithContentRect: NSMakeRect(200,200,200,300) + styleMask: NSBorderlessWindowMask | NSTitledWindowMask + backing: NSBackingStoreBuffered + defer: YES]; + + _label = [[NSTextField alloc] initWithFrame: NSMakeRect(5,275,80,20)]; + [_label setStringValue: @"New model"]; + [_label setEditable: NO]; + [_label setSelectable: NO]; + [_label setBezeled: NO]; + [_label setBordered: NO]; + [_label setBackgroundColor: [NSColor windowBackgroundColor]]; + + brws_adaptors = [[NSBrowser alloc] initWithFrame: NSMakeRect(5,30,190,240)]; + [brws_adaptors setDelegate: self]; + [brws_adaptors addColumn]; + [brws_adaptors setTitle: @"Available adaptors" ofColumn: 0]; + [brws_adaptors setAllowsEmptySelection: NO]; + [brws_adaptors setTarget:self]; + [brws_adaptors setDoubleAction:@selector(ok:)]; + + btn_ok = [[NSButton alloc] initWithFrame: NSMakeRect(5,5,50,20)]; + [btn_ok setTitle: @"ok"]; + [btn_ok setTarget: self]; + [btn_ok setAction: @selector(ok:)]; + + btn_cancel = [[NSButton alloc] initWithFrame: NSMakeRect(60,5,50,20)]; + [btn_cancel setTitle: @"cancel"]; + [btn_cancel setTarget: self]; + [btn_cancel setAction: @selector(cancel:)]; + + [[_window contentView] addSubview: _label]; + [[_window contentView] addSubview: brws_adaptors]; + [[_window contentView] addSubview: btn_ok]; + [[_window contentView] addSubview: btn_cancel]; + + RELEASE(_label); + RELEASE(brws_adaptors); + RELEASE(btn_ok); + RELEASE(btn_cancel); + } + return self; +} + +- (NSString *) runAdaptorsPanel +{ + NSString *selection; + BOOL response = NO; + + if ([NSApp runModalForWindow:_window] == NSRunAbortedResponse) + { + selection = nil; + } + else + { + selection = [[brws_adaptors selectedCell] stringValue]; + } + [_window orderOut:self]; + return selection; +} + +/* button actions */ + +- (void) ok: (id)sender +{ + [NSApp stopModalWithCode:NSRunStoppedResponse]; +} + +- (void) cancel: (id)sender +{ + [NSApp stopModalWithCode:NSRunAbortedResponse]; +} + +/* NSBrowser delegate stuff */ + +- (int) browser:(id)sender numberOfRowsInColumn:(int)column +{ + return [_adaptorNames count]; +} + +- (void)browser:(NSBrowser*)sender + willDisplayCell:(NSBrowserCell*)cell + atRow:(int)row + column:(int)column +{ + [cell setLeaf:YES]; + [cell setTitle: [_adaptorNames objectAtIndex:row]]; +} + + + +@end + diff --git a/DBModeler/COPYING b/DBModeler/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/DBModeler/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/DBModeler/DefaultColumnProvider.h b/DBModeler/DefaultColumnProvider.h new file mode 100644 index 0000000..f3e53c7 --- /dev/null +++ b/DBModeler/DefaultColumnProvider.h @@ -0,0 +1,39 @@ +#ifndef __DefaultColumnProvider_H_ +#define __DefaultColumnProvider_H_ + +/* + DefaultColumnProvider.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +NSMutableArray *DefaultAttributeColumns; +NSMutableArray *DefaultEntityColumns; +NSMutableArray *DefaultRelationshipColumns; + +@interface DefaultColumnProvider : NSObject +{ + +} +@end + +#endif // __DefaultColumnProvider_H_ diff --git a/DBModeler/DefaultColumnProvider.m b/DBModeler/DefaultColumnProvider.m new file mode 100644 index 0000000..a9c809b --- /dev/null +++ b/DBModeler/DefaultColumnProvider.m @@ -0,0 +1,232 @@ +/** + DefaultColumnProvider.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include "DefaultColumnProvider.h" +#include "ModelerEntityEditor.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define DICTSIZE(dict) (sizeof(dict) / sizeof(dict[0])) +#define uhuh (id)1 +static DefaultColumnProvider *_sharedDefaultColumnProvider; +static NSMutableDictionary *_aspectsAndKeys; + +/* object key default */ +static id attribute_columns[][3] = { + @"allowsNull", @"Allows null", nil, + @"isClassProperty", @"Class property", uhuh, + @"columnName", @"Column name", uhuh, + @"definition", @"Definition", nil, + @"externalType", @"External Type", uhuh, + @"isUsedForLocking", @"Locking", uhuh, + @"name", @"Name", uhuh, + @"precision", @"Precision", nil, + @"isPrimaryKey", @"Primary key", uhuh, + @"readFormat", @"Read format", nil, + @"scale", @"Scale", nil, + @"valueClassName", @"Value class name", uhuh, + @"valueType", @"Value type", nil, + @"width", @"Width", uhuh, + @"writeFormat", @"Write format", nil +}; + +static id relationship_columns[][3]= { + @"isClassProperty", @"Class Property", uhuh, + @"definition", @"Definition", nil, + @"name", @"Name", uhuh, + @"destinationEntity.name", @"Destination Entity", uhuh + +}; + +static id entity_columns[][3] = { + @"name", @"Name", uhuh, + @"className", @"Class name", uhuh, + @"externalName", @"External name", uhuh, + @"externalQuery", @"External query", nil, + @"parentEntity.name", @"Parent", nil + +}; + +@implementation DefaultColumnProvider +/* function to create a NSDictionary out of the c arrays.. + * which looks like + { + Class = { + columnName1 = "aspectKey1"; + columnName2 = "aspectKey2"; + }; + + Class2 = { + otherColumnName = "otherAspectKey"; + }; + } + * or something not sure if id columns[][2] would work as a method so i'll use + * a function.. it _should_ but iirc buggy somewhere (forwarding?) */ +void registerColumnsForClass(id columns[][3], int count, Class aClass,NSMutableArray *defaultColumnsArray) +{ + id *objects; + id *keys; + int i,c; + size_t size; + NSDictionary *tmp; + size = (count * sizeof(id)); + + objects = (id *)NSZoneMalloc([_sharedDefaultColumnProvider zone], size); + keys = (id *)NSZoneMalloc([_sharedDefaultColumnProvider zone], size); + + for (i = 0; i < count; i++) + { + objects[i] = columns[i][0]; + keys[i] = columns[i][1]; + if (columns[i][2] == uhuh) + { + [defaultColumnsArray addObject:keys[i]]; + } + } + tmp = [NSDictionary dictionaryWithObjects:objects + forKeys:keys + count:count]; + [EOMApp registerColumnNames: [tmp allKeys] + forClass: aClass + provider:_sharedDefaultColumnProvider]; + NSZoneFree([_sharedDefaultColumnProvider zone], objects); + NSZoneFree([_sharedDefaultColumnProvider zone], keys); + + [_aspectsAndKeys setObject: tmp + forKey: aClass]; +} + ++ (void)initialize +{ + + DefaultEntityColumns = [[NSMutableArray alloc] init]; + DefaultAttributeColumns = [[NSMutableArray alloc] init]; + DefaultRelationshipColumns = [[NSMutableArray alloc] init]; + + _sharedDefaultColumnProvider = [[self alloc] init]; + _aspectsAndKeys = [[NSMutableDictionary alloc] init]; + registerColumnsForClass(attribute_columns, + DICTSIZE(attribute_columns), + [EOAttribute class], + DefaultAttributeColumns); + registerColumnsForClass(entity_columns, + DICTSIZE(entity_columns), + [EOEntity class], + DefaultEntityColumns); + registerColumnsForClass(relationship_columns, + DICTSIZE(relationship_columns), + [EORelationship class], + DefaultRelationshipColumns); +} + +- (NSCell *)cellForColumnNamed:(NSString *)name +{ + /* TODO need a switch button for "Locking" and "Allows null" */ + if ([name isEqual:@"Primary key"]) + { + NSButtonCell *cell = [[NSButtonCell alloc] initImageCell:nil]; + + [cell setButtonType:NSSwitchButton]; + [cell setImagePosition:NSImageOnly]; + [cell setBordered:NO]; + [cell setBezeled:NO]; + [cell setAlternateImage:[NSImage imageNamed:@"Key_On"]]; + [cell setControlSize: NSSmallControlSize]; + [cell setEditable:YES]; + return cell; + } + else if ([name isEqual:@"Class property"]) + { + NSButtonCell *cell = [[NSButtonCell alloc] initImageCell:nil]; + + [cell setButtonType:NSSwitchButton]; + [cell setImagePosition:NSImageOnly]; + [cell setBordered:NO]; + [cell setBezeled:NO]; + [cell setAlternateImage:[NSImage imageNamed:@"ClassProperty_On"]]; + [cell setControlSize: NSSmallControlSize]; + [cell setEditable:YES]; + return cell; + } + else if ([name isEqual:@"Locking"]) + { + NSButtonCell *cell = [[NSButtonCell alloc] initImageCell:nil]; + + [cell setButtonType:NSSwitchButton]; + [cell setImagePosition:NSImageOnly]; + [cell setBordered:NO]; + [cell setBezeled:NO]; + [cell setAlternateImage:[NSImage imageNamed:@"ClassProperty_On"]]; + [cell setControlSize: NSSmallControlSize]; + [cell setEditable:YES]; + return cell; + } + else + { + NSTextFieldCell *cell = [[NSTextFieldCell alloc] initTextCell:@""]; + [cell setEnabled:YES]; + [cell setEditable:YES]; + [cell setScrollable: YES]; + return cell; + } +} + +- (void)initColumn:(NSTableColumn *)tc + class:(Class)class + name:(NSString *)columnName + displayGroup:(EODisplayGroup *)displayGroup + document:(EOModelerDocument *)doc +{ + EOColumnAssociation *association; + NSCell *cell; + NSString *aspectKey; + NSString *aspect; + + aspectKey = [[_aspectsAndKeys objectForKey:class] objectForKey:columnName]; + aspect = @"value"; + association = [[EOColumnAssociation alloc] initWithObject:tc]; + [[tc headerCell] setStringValue:columnName]; + cell = [self cellForColumnNamed:columnName]; + [tc setEditable:[cell isEditable]]; + [tc setDataCell:cell]; + [association bindAspect:aspect displayGroup:displayGroup key:aspectKey]; + [association establishConnection]; + [association release]; +} + +@end diff --git a/DBModeler/EOAdditions.h b/DBModeler/EOAdditions.h new file mode 100644 index 0000000..e09db2c --- /dev/null +++ b/DBModeler/EOAdditions.h @@ -0,0 +1,36 @@ +#ifndef __EOAdditions_H_ +#define __EOAdditions_H_ + +/* + EOAdditions.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +/* these use NSNumbers because they are used in key value coding. */ +@interface EOAttribute (ModelerAdditions) +- (NSNumber *) isPrimaryKey; +- (void) setIsPrimaryKey:(NSNumber *)flag; +- (NSNumber *) isClassProperty; +- (void) setIsClassProperty:(NSNumber *)flag; +@end + +#endif // __EOAdditions_H_ diff --git a/DBModeler/EOAdditions.m b/DBModeler/EOAdditions.m new file mode 100644 index 0000000..5fb26f0 --- /dev/null +++ b/DBModeler/EOAdditions.m @@ -0,0 +1,124 @@ +/** + EOAdditions.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include +#include +#include + +#include +#include + +/* this is all stuff for key value coding.. */ +static inline NSNumber * isClassProperty(id self) +{ + return [NSNumber numberWithBool: [[[self entity] classProperties] containsObject:self]]; +} + +static inline void setIsClassProperty(id self, NSNumber *flag) +{ + BOOL isProp = [flag boolValue]; + NSArray *props = RETAIN([[self entity] classProperties]); + + if (isProp) + { + if (![props containsObject:self]) + [[self entity] setClassProperties: [props arrayByAddingObject:self]]; + } + else + { + if ([props containsObject:self]) + { + NSMutableArray *newProps = [NSMutableArray arrayWithArray:props]; + [newProps removeObject: self]; + [[self entity] setClassProperties: newProps]; + } + } + RELEASE(props); +} + +@implementation EOAttribute (ModelerAdditions) + +- (NSNumber *) isPrimaryKey +{ + return [NSNumber numberWithBool: [[[self entity] primaryKeyAttributes] containsObject:self]]; +} + +- (void) setIsPrimaryKey:(NSNumber *)flag +{ + BOOL isKey = [flag boolValue]; + NSArray *pka = RETAIN([[self entity] primaryKeyAttributes]); + + if (isKey) + { + if (![pka containsObject:self]) + [[self entity] setPrimaryKeyAttributes: [pka arrayByAddingObject:self]]; + } + else + { + if ([pka containsObject:self]) + { + NSMutableArray *newPks = [NSMutableArray arrayWithArray:pka]; + [newPks removeObject: self]; + [[self entity] setPrimaryKeyAttributes: newPks]; + + } + } + RELEASE(pka); +} + +- (NSNumber *) isClassProperty +{ + return isClassProperty(self); +} + +- (void) setIsClassProperty:(NSNumber *)flag +{ + return setIsClassProperty(self, flag); +} + +- (NSNumber *) isUsedForLocking +{ + return [NSNumber numberWithBool:NO]; + /* FIXME */ +} + +- (void) setIsUsedForLocking:(NSNumber *)flag +{ + /* FIXME */ +} +@end + + +@implementation EORelationship (ModelerAdditions) +- (NSNumber *) isClassProperty +{ + return isClassProperty(self); +} + +- (void) setIsClassProperty:(NSNumber *)flag +{ + return setIsClassProperty(self, flag); +} +@end diff --git a/DBModeler/GNUmakefile b/DBModeler/GNUmakefile new file mode 100644 index 0000000..8b24f20 --- /dev/null +++ b/DBModeler/GNUmakefile @@ -0,0 +1,37 @@ +include $(GNUSTEP_MAKEFILES)/common.make +include $(GNUSTEP_MAKEFILES)/Auxiliary/gdl2.make + +APP_NAME = DBModeler +DBModeler_SUBPROJECTS=Inspectors + +ADDITIONAL_LIB_DIRS+=-L../EOAccess/$(GNUSTEP_OBJ_DIR) +ADDITIONAL_LIB_DIRS+=-L../EOControl/$(GNUSTEP_OBJ_DIR) + +ifeq ($(FOUNDATION_LIB), apple) +ADDITIONAL_LIB_DIRS+= -F../EOModeler +ADDITIONAL_INCLUDE_DIRS+= -F../EOModeler +else +ADDITIONAL_INCLUDE_DIRS= -I.. +ADDITIONAL_LIB_DIRS= -L../EOModeler/$(GNUSTEP_OBJ_DIR) +endif + +ADDITIONAL_NATIVE_LIBS += EOInterface gnustep-db2modeler + +$(APP_NAME)_RESOURCE_FILES = \ + Resources/Key_On.tiff \ + Resources/ClassProperty_On.tiff \ + Resources/ModelDrag.tiff + +$(APP_NAME)_OBJC_FILES = \ + main.m \ + Modeler.m \ + AdaptorsPanel.m \ + MainModelEditor.m \ + ModelerEntityEditor.m \ + DefaultColumnProvider.m \ + KVDataSource.m \ + ModelerAttributeEditor.m \ + EOAdditions.m \ + ModelerTableEmbedibleEditor.m + +include $(GNUSTEP_MAKEFILES)/application.make diff --git a/DBModeler/Inspectors/AttributeInspector.gorm/data.classes b/DBModeler/Inspectors/AttributeInspector.gorm/data.classes new file mode 100644 index 0000000..c17c810 --- /dev/null +++ b/DBModeler/Inspectors/AttributeInspector.gorm/data.classes @@ -0,0 +1,12 @@ +{ + "## Comment" = "Do NOT change this file, Gorm maintains it"; + EOMInspector = { + Actions = ( + ); + Outlets = ( + view, + window + ); + Super = NSObject; + }; +} \ No newline at end of file diff --git a/DBModeler/Inspectors/AttributeInspector.gorm/data.info b/DBModeler/Inspectors/AttributeInspector.gorm/data.info new file mode 100644 index 0000000..a98a343 Binary files /dev/null and b/DBModeler/Inspectors/AttributeInspector.gorm/data.info differ diff --git a/DBModeler/Inspectors/AttributeInspector.gorm/objects.gorm b/DBModeler/Inspectors/AttributeInspector.gorm/objects.gorm new file mode 100644 index 0000000..731bdb2 Binary files /dev/null and b/DBModeler/Inspectors/AttributeInspector.gorm/objects.gorm differ diff --git a/DBModeler/Inspectors/AttributeInspector.h b/DBModeler/Inspectors/AttributeInspector.h new file mode 100644 index 0000000..96c1ee4 --- /dev/null +++ b/DBModeler/Inspectors/AttributeInspector.h @@ -0,0 +1,10 @@ +#include + + +@interface AttributeInspector : EOMInspector +{ + +} + +@end + diff --git a/DBModeler/Inspectors/AttributeInspector.m b/DBModeler/Inspectors/AttributeInspector.m new file mode 100644 index 0000000..495fee6 --- /dev/null +++ b/DBModeler/Inspectors/AttributeInspector.m @@ -0,0 +1,16 @@ +#include "AttributeInspector.h" + +@implementation AttributeInspector + +- (float) displayOrder +{ + return 0; +} + +- (void) refresh +{ + +} + +@end + diff --git a/DBModeler/Inspectors/GNUmakefile b/DBModeler/Inspectors/GNUmakefile new file mode 100644 index 0000000..067480e --- /dev/null +++ b/DBModeler/Inspectors/GNUmakefile @@ -0,0 +1,13 @@ +include $(GNUSTEP_MAKEFILES)/common.make +SUBPROJECT_NAME=Inspectors +ADDITIONAL_INCLUDE_DIRS+=-I../../ + +Inspectors_HAS_RESOURCE_BUNDLE=yes + +Inspectors_RESOURCE_FILES=RelationshipInspector.gorm +Inspectors_OBJC_FILES=RelationshipInspector.m + +Inspectors_RESOURCE_FILES+=AttributeInspector.gorm +Inspectors_OBJC_FILES+=AttributeInspector.m + +include $(GNUSTEP_MAKEFILES)/subproject.make diff --git a/DBModeler/Inspectors/RelationshipInspector.gorm/data.classes b/DBModeler/Inspectors/RelationshipInspector.gorm/data.classes new file mode 100644 index 0000000..5a2527f --- /dev/null +++ b/DBModeler/Inspectors/RelationshipInspector.gorm/data.classes @@ -0,0 +1,40 @@ +{ + "## Comment" = "Do NOT change this file, Gorm maintains it"; + EOMInspector = { + Actions = ( + ); + Outlets = ( + view, + window + ); + Super = NSObject; + }; + FirstResponder = { + Actions = ( + "cardinalityChanged:", + "connectionChanged:", + "nameChanged:", + "semanticChanged:" + ); + Super = NSObject; + }; + RelationshipInspector = { + Actions = ( + "connectionChanged:", + "cardinalityChanged:", + "nameChanged:", + "semanticChanged:" + ); + Outlets = ( + name_textField, + model_popup, + destEntity_tableView, + joinCardinality_matrix, + joinSemantic_popup, + srcAttrib_tableView, + destAttrib_tableView, + connect_button + ); + Super = EOMInspector; + }; +} \ No newline at end of file diff --git a/DBModeler/Inspectors/RelationshipInspector.gorm/data.info b/DBModeler/Inspectors/RelationshipInspector.gorm/data.info new file mode 100644 index 0000000..a98a343 Binary files /dev/null and b/DBModeler/Inspectors/RelationshipInspector.gorm/data.info differ diff --git a/DBModeler/Inspectors/RelationshipInspector.gorm/objects.gorm b/DBModeler/Inspectors/RelationshipInspector.gorm/objects.gorm new file mode 100644 index 0000000..409c506 Binary files /dev/null and b/DBModeler/Inspectors/RelationshipInspector.gorm/objects.gorm differ diff --git a/DBModeler/Inspectors/RelationshipInspector.h b/DBModeler/Inspectors/RelationshipInspector.h new file mode 100644 index 0000000..3cbc0e1 --- /dev/null +++ b/DBModeler/Inspectors/RelationshipInspector.h @@ -0,0 +1,21 @@ +#include +#include + +@class EOModel; +@class EOEntity; +@interface RelationshipInspector : EOMInspector +{ + IBOutlet NSTextField *name_textField; + IBOutlet NSPopUpButton *model_popup; + IBOutlet NSMatrix *joinCardinality_matrix; + IBOutlet NSPopUpButton *joinSemantic_popup; + IBOutlet NSTableView *destEntity_tableView; + IBOutlet NSTableView *srcAttrib_tableView; + IBOutlet NSTableView *destAttrib_tableView; + IBOutlet NSButton *connect_button; +} + +- (IBAction) connectionChanged:(id)sender; +- (IBAction) nameChanged:(id)sender; +@end + diff --git a/DBModeler/Inspectors/RelationshipInspector.m b/DBModeler/Inspectors/RelationshipInspector.m new file mode 100644 index 0000000..1b7f56b --- /dev/null +++ b/DBModeler/Inspectors/RelationshipInspector.m @@ -0,0 +1,186 @@ +#include "RelationshipInspector.h" + +#include +#include +#include +#include + +#include +#include + +#include + +@implementation RelationshipInspector +- (void) awakeFromNib +{ + [destEntity_tableView setAllowsEmptySelection:NO]; + [srcAttrib_tableView setAllowsEmptySelection:NO]; + [destAttrib_tableView setAllowsEmptySelection:NO]; +} +- (float) displayOrder +{ + return 0; +} +- (BOOL) canInspectObject:(id)anObject +{ + return [anObject isKindOfClass:[EORelationship class]]; +} + +- (void) refresh +{ + EOModel *activeModel = [[EOMApp activeDocument] model]; + EOEntity *destEntity; + EOAttribute *srcAttrib, *destAttrib; + NSArray *srcAttribs; + NSArray *destAttribs; + unsigned int row; + + + [name_textField setStringValue:[(EORelationship *)[self selectedObject] name]]; + + + + /* it is important that the destEntity has a selected row before the destAttrib tableview + * reloads data */ + [destEntity_tableView reloadData]; + destEntity = [[self selectedObject] destinationEntity]; + if (destEntity) + { + row = [[activeModel entities] indexOfObject:destEntity]; + if (row == NSNotFound) + row = 0; + } + else if ([destEntity_tableView numberOfRows]) + row = 0; + [destEntity_tableView selectRow:row byExtendingSelection:NO]; + + srcAttribs = [[self selectedObject] sourceAttributes]; + if (srcAttribs && [srcAttribs count]) + srcAttrib = [srcAttribs objectAtIndex:0]; + else + srcAttrib = nil; + + [srcAttrib_tableView reloadData]; + if (srcAttrib) + { + // FIXME!!!! when there is no srcAttrib we segfault when calling isEqual: so we use indexOfObjectIdenticalTo: + row = [[[[self selectedObject] entity] attributes] indexOfObject:srcAttrib]; + if (row == NSNotFound) + row = 0; + } + else if ([srcAttrib_tableView numberOfRows]) + row = 0; + [srcAttrib_tableView selectRow:row byExtendingSelection:NO]; + + destAttribs = [[self selectedObject] destinationAttributes]; + if (destAttribs && [destAttribs count]) + destAttrib = [destAttribs objectAtIndex:0]; + else + destAttrib = nil; + [destAttrib_tableView reloadData]; + if (destAttrib) + { + // FIXME!!!! when there is no destAttrib we segfault when calling isEqual: so we use indexOfObjectIdenticalTo: + row = [[[[self selectedObject] destinationEntity] attributes] indexOfObject:destAttrib]; + if (row == NSNotFound) + row = 0; + } + else if ([destAttrib_tableView numberOfRows]) + row = 0; + [destAttrib_tableView selectRow:row byExtendingSelection:NO]; + + [connect_button setState: ([[self selectedObject] destinationEntity] == nil) ? NSOffState : NSOnState]; + + [joinCardinality_matrix selectCellWithTag:[[self selectedObject] isToMany]]; + [joinSemantic_popup selectItemAtIndex: [joinSemantic_popup indexOfItemWithTag: [[self selectedObject] joinSemantic]]]; +} + +- (int) numberOfRowsInTableView:(NSTableView *)tv +{ + EOModel *activeModel = [[EOMApp activeDocument] model]; + if (tv == destEntity_tableView) + return [[activeModel entities] count]; + else if (tv == srcAttrib_tableView) + return [[(EOEntity *)[[self selectedObject] entity] attributes] count]; + else if (tv == destAttrib_tableView) + { + int selectedRow = [destEntity_tableView selectedRow]; + if (selectedRow == -1 || selectedRow == NSNotFound) + return 0; + return [[(EOEntity *)[[activeModel entities] objectAtIndex:[destEntity_tableView selectedRow]] attributes] count]; + + } +} + +- (id) tableView:(NSTableView *)tv +objectValueForTableColumn:(NSTableColumn *)tc +row:(int)rowIndex +{ + EOModel *activeModel = [[EOMApp activeDocument] model]; + if (tv == destEntity_tableView) + { + return [(EOEntity *)[[activeModel entities] objectAtIndex:rowIndex] name]; + } + else if (tv == srcAttrib_tableView) + { + return [(EOAttribute *)[[(EOEntity *)[[self selectedObject] entity] attributes] objectAtIndex:rowIndex] name]; + } + else if (tv == destAttrib_tableView) + { + int selectedRow = [destEntity_tableView selectedRow]; + if (selectedRow == NSNotFound) + [destEntity_tableView selectRow:0 byExtendingSelection:NO]; + return [(EOAttribute *)[[(EOEntity *)[[activeModel entities] objectAtIndex:[destEntity_tableView selectedRow]] + attributes] objectAtIndex:rowIndex] name]; + } +} + +- (void) tableViewSelectionDidChange:(NSNotification *)notif +{ + NSTableView *tv = [notif object]; + + if (tv == destEntity_tableView) + { + [destAttrib_tableView reloadData]; + } +} +- (void) connectionChanged:(id)sender +{ + EOEntity *destEntity; + EOAttribute *srcAttrib; + EOAttribute *destAttrib; + EOModel *model; + EOJoin *newJoin; + + model = [[EOMApp activeDocument] model]; + + destEntity = [[model entities] objectAtIndex:[destEntity_tableView selectedRow]]; + destAttrib = [[destEntity attributes] objectAtIndex:[destAttrib_tableView selectedRow]]; + srcAttrib = [[[[self selectedObject] entity] attributes] objectAtIndex:[srcAttrib_tableView selectedRow]]; + + newJoin = [[EOJoin alloc] initWithSourceAttribute:srcAttrib destinationAttribute:destAttrib]; + [[self selectedObject] addJoin:newJoin]; + [newJoin release]; +} + +- (void) nameChanged:(id)sender +{ + NSString *name = [name_textField stringValue]; + + [(EORelationship *)[self selectedObject] setName:name]; +} + +- (void) semanticChanged:(id)sender +{ + /* the tag in the nib must match the values in the EOJoinSemantic enum */ + [[self selectedObject] setJoinSemantic: [[sender selectedItem] tag]]; + +} + +- (void) cardinalityChanged:(id)sender +{ + /* the tag in the nib for to-one must be 0 to-many 1 */ + [[self selectedObject] setToMany: [[sender selectedCell] tag]]; +} +@end + diff --git a/DBModeler/KVDataSource.h b/DBModeler/KVDataSource.h new file mode 100644 index 0000000..0fa22c5 --- /dev/null +++ b/DBModeler/KVDataSource.h @@ -0,0 +1,48 @@ +#ifndef __KVDataSource_H_ +#define __KVDataSource_H_ + +/* + KVDataSource.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +@interface KVDataSource : EODataSource +{ + id _dataObject; + EOEditingContext *_context; + EOClassDescription *_classDescription; + NSString *_key; +} + +- (id) initWithClassDescription: (EOClassDescription *)classDescription + editingContext: (EOEditingContext *) context; +- (void) setDataObject: (id)object; +- (id) dataObject; +- (void) setKey:(NSString *)key; + +/** result of [_dataObject -valueForKey:key] should be an array */ +- (NSString *)key; + +@end + +#endif // __KVDataSource_H_ diff --git a/DBModeler/KVDataSource.m b/DBModeler/KVDataSource.m new file mode 100644 index 0000000..3263207 --- /dev/null +++ b/DBModeler/KVDataSource.m @@ -0,0 +1,172 @@ +/** + KVDataSource.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include "KVDataSource.h" + +@implementation KVDataSource + +- (id) initWithClassDescription: (EOClassDescription *)classDescription + editingContext: (EOEditingContext *)context +{ + if ((self = [super init])) + { + _classDescription = RETAIN(classDescription); + _context = RETAIN(context); + _dataObject = nil; + _key = nil; + } + return self; +} + +- (void) dealloc +{ + DESTROY(_classDescription); + DESTROY(_context); + DESTROY(_dataObject); + DESTROY(_key); + [super dealloc]; +} + +- (void) encodeWithCoder: (NSCoder *)encoder +{ + +} + +- (id) initWithCoder: (NSCoder *)decoder +{ +return self; +} +- (id) createObject +{ +/* id object; + EOEditingContext *edCtxt; + + if ([_key isEqual:@"entities"]) + object = [EOEntity new]; + if ([_key isEqual:@"attributes"]) + object = [EOAttribute new]; + + if (object && (edCtxt = [self editingContext])) + [edCtxt insertObject:object]; + + return AUTORELEASE(object); +*/ + [[NSException exceptionWithName:NSInternalInconsistencyException + reason: [NSString stringWithFormat:@"%@ not supported by %@", NSStringFromSelector(_cmd), NSStringFromClass([self class])] + userInfo:nil] raise]; +} +- (void) insertObject:(id)object +{ +/* + if ([object isKindOfClass:[EOEntity class]]) + { + [_dataObject addEntity:object]; + } + else if ([object isKindOfClass:[EOAttribute class]]) + { + [_dataObject addAttribute:object]; + } +*/ + [[NSException exceptionWithName:NSInternalInconsistencyException + reason: [NSString stringWithFormat:@"%@ not supported by %@", NSStringFromSelector(_cmd), NSStringFromClass([self class])] + userInfo:nil] raise]; +} + +- (void) deleteObject:(id)object +{ + // TODO +} + +- (NSArray *)fetchObjects +{ + return [_dataObject valueForKey:_key]; +} + +- (EOEditingContext *)editingContext +{ + return _context; +} + +- (void) qualifyWithRelationshipKey:(NSString *)key ofObject:(id) sourceObject +{ + +} + +- (EODataSource *) dataSourceQualifiedByKey: (NSString *)key +{ + +} + +- (EOClassDescription *)classDescriptionForObjects +{ + return _classDescription; +} + +- (NSArray *)qualifierBindingKeys +{ + return nil; +} + +- (void) setQualifierBindings:(NSDictionary *)bindings +{ + +} + +- (NSDictionary *)qualifierBindings +{ + return nil; +} + +- (void) setDataObject:(id)object +{ + ASSIGN(_dataObject,object); +} + +- (id) dataObject +{ + return _dataObject; +} + +- (void) setKey:(NSString *)key +{ + ASSIGN(_key,key); +} + +- (NSString *) key +{ + return _key; +} +@end + diff --git a/DBModeler/MainModelEditor.h b/DBModeler/MainModelEditor.h new file mode 100644 index 0000000..0a78358 --- /dev/null +++ b/DBModeler/MainModelEditor.h @@ -0,0 +1,42 @@ +#ifndef __MainModelEditor_H_ +#define __MainModelEditor_H_ + +/* + MainModelerEditor.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include +#include +#include + +@interface MainModelEditor : EOModelerCompoundEditor +{ + NSBox *_box; + NSWindow *_window; + NSOutlineView *_iconPath; +} + +@end + +#endif diff --git a/DBModeler/MainModelEditor.m b/DBModeler/MainModelEditor.m new file mode 100644 index 0000000..add1a24 --- /dev/null +++ b/DBModeler/MainModelEditor.m @@ -0,0 +1,494 @@ +/** + MainModelEditor.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include "MainModelEditor.h" +#include "ModelerEntityEditor.h" + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +//#define DEBUG_STUFF 1 + +@interface ModelerOutlineView : NSOutlineView +@end +@implementation ModelerOutlineView + +- (NSImage *) dragImageForRows:(NSArray *)dragRows + event: (NSEvent *)dragEvent + dragImageOffset: (NSPoint *)dragImageOffset +{ + id foo = [self itemAtRow:[[dragRows objectAtIndex:0] intValue]]; + NSImage *img = nil; + + if ([foo isKindOfClass: [EOEntity class]]) + { + img = [NSImage imageNamed:@"ModelDrag"]; + [img setScalesWhenResized:NO]; + } + return img; +} +@end +@implementation MainModelEditor +- (id) initWithDocument:(EOModelerDocument *)document +{ + if (self = [super initWithDocument:document]) + { + NSTableColumn *_col; + NSSplitView *vSplit = [[NSSplitView alloc] initWithFrame:NSMakeRect(0,0,400,400)]; + NSScrollView *sv = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,100,400)]; + // NSImageCell *_cell; + + [vSplit setVertical:YES]; + + + _iconPath = [[ModelerOutlineView alloc] initWithFrame:NSMakeRect(0,0,100,400)]; + [_iconPath setIndentationPerLevel:8.0]; + [_iconPath setIndentationMarkerFollowsCell:YES]; + + [_iconPath setDelegate:self]; + [_iconPath setDataSource:self]; + //_cell = [[NSImageCell alloc] init]; + _col = [(NSTableColumn *)[NSTableColumn alloc] initWithIdentifier:@"name"]; + [_iconPath addTableColumn:_col]; + [_iconPath setOutlineTableColumn:AUTORELEASE(_col)]; + //[[_iconPath tableColumnWithIdentifier:@"name"] setDataCell:_cell]; + [_iconPath setAutoresizesAllColumnsToFit:YES]; + [_iconPath sizeToFit]; + + _window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,400) + styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask | NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + + [sv setHasHorizontalScroller:YES]; + [sv setHasVerticalScroller:YES]; + [sv setAutoresizingMask: NSViewWidthSizable]; + [_iconPath setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; + [sv setDocumentView:_iconPath]; + RELEASE(_iconPath); + [vSplit addSubview:sv]; + RELEASE(sv); + + + _box = [[NSBox alloc] initWithFrame:NSMakeRect(0,0,300,400)]; + [_box setTitle:@""]; + [_box setBorderType:NSNoBorder]; + [_box setAutoresizesSubviews:YES]; + [_box setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + [vSplit addSubview: _box]; + RELEASE(_box); + + [vSplit setAutoresizesSubviews:YES]; + [vSplit setAutoresizingMask: NSViewWidthSizable + | NSViewHeightSizable]; + [vSplit adjustSubviews]; + [[_window contentView] addSubview:vSplit]; + RELEASE(vSplit); + + /* so addEntity: addAttribute: ... menu items work */ + [_window setDelegate: document]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector:@selector(ecStuff:) + name: EOObjectsChangedInEditingContextNotification + object: [[self document] editingContext]]; + + [self setViewedObjectPath:[NSArray arrayWithObject:[document model]]]; + } + return self; +} +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver: self]; + RELEASE(_window); + [super dealloc]; +} +- (void) ecStuff:(NSNotification *)notif +{ + if ([[notif object] isKindOfClass:[EOEditingContext class]]) + { + int i,c; + NSArray *objects = [[notif userInfo] objectForKey:EOUpdatedKey]; + + for (i = 0, c = [objects count]; i < c; i++) + [_iconPath reloadItem:[objects objectAtIndex:i] reloadChildren:YES]; +#if 0 + objects = [[notif userInfo] objectForKey:EOInsertedKey]; + for (i = 0, c = [objects count]; i < c; i++) + [_iconPath reloadItem:[objects objectAtIndex:i] reloadChildren:YES]; + + objects = [[notif userInfo] objectForKey:EODeletedKey]; + for (i = 0, c = [objects count]; i < c; i++) + [_iconPath reloadItem:[objects objectAtIndex:i] reloadChildren:YES]; +#endif + + } +} + +- (void)activateEmbeddedEditor:(EOModelerEmbedibleEditor *)editor +{ + NSView *mainView = [editor mainView]; + int i, count; + NSArray *subviews; + + subviews = [mainView subviews]; + count = [subviews count]; + [super activateEmbeddedEditor:editor]; + for (i = 0; i < count; i++) + { + NSView *aView = [subviews objectAtIndex:i]; + + [aView setAutoresizesSubviews:YES]; + [aView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + } + [mainView setAutoresizesSubviews:YES]; + [mainView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + [mainView setFrame: [_box frame]]; + + [_box setContentView: mainView]; + [_box setNeedsDisplay:YES]; +} + +- (void)activateEditorWithClass:(Class)embedibleEditorClass +{ + [super activateEditorWithClass:embedibleEditorClass]; + [self activateEmbeddedEditor: + [self embedibleEditorOfClass:embedibleEditorClass]]; + [_iconPath reloadData]; +} + +- (void) activate +{ + if (![_window isVisible] || ![_window isKeyWindow]) + { + [_window makeKeyAndOrderFront:self]; + [self activateEmbeddedEditor: + [self embedibleEditorOfClass: + NSClassFromString(@"ModelerEntityEditor")]]; + + } + [_iconPath reloadData]; + [super activate]; +} + +- (void) viewSelectedObject +{ + id selection; + if ([[self selectionWithinViewedObject] count] == 0) + { + NSLog(@"view count == 0, obj:"); + return; + } + + selection = [[self selectionWithinViewedObject] objectAtIndex:0]; +#if DEBUG_STUFF == 1 + GSPrintf(stderr, @"viewing %@(%@)\n", NSStringFromClass([selection class]), [(EOModel *)selection name]); +#endif + if ([[self activeEditor] canSupportCurrentSelection]) + [self activateEmbeddedEditor: [self activeEditor]]; + else + { + NSArray *friends = [[self activeEditor] friendEditorClasses]; + int editorsCount; + int i,j,c; + + /* first look for instances of our friend classes that can support the + current selection */ + for (i = 0, c = [friends count]; i < c; i++) + { + id friend = [friends objectAtIndex:i]; + for (j = 0,editorsCount = [_editors count]; j < editorsCount; j++) + { + if ([_editors isKindOfClass: friend]) + { + id friendEditor = [_editors objectAtIndex:j]; + + if ([friend canSupportCurrentSelection]) + { + [self activateEmbeddedEditor:friend]; + [super viewSelectedObject]; + return; + } + } + } + } + /* instantiate friends to see if we can support the current selection */ + for (i = 0,c = [friends count]; i < c; i++) + { + id friendClass = [friends objectAtIndex:i]; + id friend = [[friendClass alloc] initWithParentEditor:self]; + { + if ([friend canSupportCurrentSelection]) + { + [self activateEmbeddedEditor:friend]; + [super viewSelectedObject]; + return; + } + else + { + [friend release]; + } + } + } + /* look for any old editor this isn't very nice... + * because it only works with registered editors, and we can only + * register instances of editors, so a) can't load on demand non-friend + * editors, or b) we should register instances of all editors */ + for (i = 0, c = [_editors count]; i < c; i++) + { + id anEditor = [_editors objectAtIndex:i]; + + if ([anEditor canSupportCurrentSelection]) + { + [self activateEmbeddedEditor:anEditor]; + [super viewSelectedObject]; + return; + } + } + + } + [super viewSelectedObject]; +} + +/* NSOutlineView datasource stuff */ +- (BOOL)outlineView: (NSOutlineView *)outlineView + isItemExpandable: (id)item +{ + BOOL ret = NO; + + if (item == nil) + ret = ([[[_document model] entities] count] > 0); + else if ([item isKindOfClass:[EOModel class]]) + ret = ([[item entities] count] > 0); + else if ([item isKindOfClass:[EOEntity class]]) + ret = ([[item relationships] count] > 0); + else if ([item isKindOfClass:[EORelationship class]]) + ret = 0; +#if DEBUG_STUFF == 1 + NSLog(@"isItemExpandable %i", ret); +#endif + return ret; +} + +- (int) outlineView: (NSOutlineView *)outlineView + numberOfChildrenOfItem: (id)item +{ + int ret = 0; + + if (item == nil) + ret = 1; + else if ([item isKindOfClass: [EOModel class]]) + ret = [[item entities] count]; + else if ([item isKindOfClass: [EOEntity class]]) + ret = [[item relationships] count]; + else if ([item isKindOfClass: [EORelationship class]]) + ret = 0; + +#if DEBUG_STUFF == 1 + NSLog(@"num children %i %@", ret, [item class]); +#endif + + return ret; +} + +- (id)outlineView: (NSOutlineView *)outlineView + child: (int)index + ofItem: (id)item +{ + id ret = @"blah."; + + if (item == nil) + ret = [_document model]; + else if ([item isKindOfClass: [EOModel class]]) + ret = [[item entities] objectAtIndex:index]; + else if ([item isKindOfClass: [EOEntity class]]) + ret = [[item relationships] objectAtIndex:index]; + else if ([item isKindOfClass: [EORelationship class]]) + ret = nil; +#if DEBUG_STUFF == 1 + NSLog(@"child %@ atIndex: %i ofItem %@", [ret class], index, [item class]); +#endif + return ret; +} + +- (id) outlineView: (NSOutlineView *)outlineView + objectValueForTableColumn: (NSTableColumn *)tableColumn + byItem: (id)item +{ + id ret; + if (item == nil) + ret = [[_document model] name]; + else + ret = [item valueForKey:@"name"]; +#if DEBUG_STUFF == 1 + NSLog(@"objectValue: %@", ret); +#endif + return ret; +} + +- (void) outlineViewSelectionDidChange:(NSNotification *)notif +{ + NSMutableArray *foo = [[NSMutableArray alloc] init]; + EOModel *bar = [_document model]; + id item = nil; + int selectedRow = [_iconPath selectedRow]; + if (selectedRow == -1) + return; + while (bar != item) + { + if (item == nil) + { + + item = [_iconPath itemAtRow:selectedRow]; + [foo insertObject:[NSArray arrayWithObject:item] atIndex:0]; + } + else if ([item isKindOfClass:[EOEntity class]]) + { + item = [item model]; + [foo insertObject:item atIndex:0]; + } + else if ([item isKindOfClass:[EORelationship class]]) + { + item = [item entity]; + [foo insertObject:item atIndex:0]; + } + } +#if DEBUG_STUFF == 1 + { + int i,c; + NSArray *selpath = [self selectionPath]; + NSLog(@"current selection path"); + for (i = 0, c = [selpath count]; i < c; i++) + { + id obj = [selpath objectAtIndex:i]; + + if ([obj isKindOfClass:[NSArray class]]) + { + int j,d; + for (j = 0, d = [obj count]; j < d; j++) + { + GSPrintf(stderr, @"* %@(%@)\n", [[obj objectAtIndex:j] class], [(EOModel *)[obj objectAtIndex:j] name]); + } + } + else + GSPrintf(stderr, @"%@(%@)\n", [obj class], [(EOModel *)obj name]); + } + NSLog(@"changing to"); + selpath = foo; + for (i = 0, c = [selpath count]; i < c; i++) + { + id obj = [selpath objectAtIndex:i]; + + if ([obj isKindOfClass:[NSArray class]]) + { + int j,d; + for (j = 0, d = [obj count]; j < d; j++) + { + GSPrintf(stderr, @"* %@(%@)\n", [[obj objectAtIndex:j] class], [(EOModel *)[obj objectAtIndex:j] name]); + } + } + else + GSPrintf(stderr, @"%@(%@)\n", [obj class], [(EOModel *)obj name]); + } + } +#endif + [self setSelectionPath:AUTORELEASE(foo)]; + [self viewSelectedObject]; +} + +- (BOOL) outlineView:(NSOutlineView *)view +writeItems:(NSArray *)rows +toPasteboard:(NSPasteboard *)pboard +{ + NSMutableArray *foo = [[NSMutableArray alloc] init]; + EOModel *bar = [_document model]; + int selectedRow = [_iconPath selectedRow]; + id item = [_iconPath itemAtRow:selectedRow]; + + if (selectedRow == -1) + return NO; + while (item != nil) + { + if (item == bar) + { + NSString *modelPath = [item valueForKey:@"path"]; + if (modelPath == nil) + { + NSRunAlertPanel(@"Error", @"Must save before dragging", @"OK",@"Cancel",nil); + return NO; + } + [foo insertObject:modelPath atIndex:0]; + item = nil; + } + else if ([item isKindOfClass:[EOEntity class]]) + { + [foo insertObject:[item valueForKey:@"name"] atIndex:0]; + item = [item model]; + } + else if ([item isKindOfClass:[EORelationship class]]) + { + [foo insertObject:[item valueForKey:@"name"] atIndex:0]; + item = [item entity]; + } + } + [pboard declareTypes: [NSArray arrayWithObject: EOMPropertyPboardType] owner:nil]; + [pboard setPropertyList:foo forType:EOMPropertyPboardType]; + return YES; +} + +#if 0 +- (void) outlineView: (NSOutlineView *)outlineView +willDisplayCell:(NSCell *)cell +forTableColumn:(NSTableColumn *)tc +item:(id)item +{ + //if (![[tc identifier] isEqual:@"name"]) +// return; + if ([item isKindOfClass:[EOModel class]]) + [cell setImage: [NSImage imageNamed:@"Model_small.tiff"]]; + if ([item isKindOfClass:[EOEntity class]]) + [cell setImage: [NSImage imageNamed:@"Entity_small.tiff"]]; + if ([item isKindOfClass:[EORelationship class]]) + [cell setImage: [NSImage imageNamed:@"Relationship_small.tiff"]]; +} +#endif +@end diff --git a/DBModeler/Modeler.h b/DBModeler/Modeler.h new file mode 100644 index 0000000..d92deeb --- /dev/null +++ b/DBModeler/Modeler.h @@ -0,0 +1,40 @@ +#ifndef __Modeler_H_ +#define __Modeler_H_ + +/* + Modeler.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +@class NSObject; + +@interface Modeler : NSObject +{ + + +} + +@end + +#endif // __Modeler_H_ + diff --git a/DBModeler/Modeler.m b/DBModeler/Modeler.m new file mode 100644 index 0000000..a8f7223 --- /dev/null +++ b/DBModeler/Modeler.m @@ -0,0 +1,250 @@ +/** + Modeler.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + +#include "Modeler.h" +#include "AdaptorsPanel.h" +#include "MainModelEditor.h" +#include "ModelerEntityEditor.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* TODO validate menu items.. */ +@interface NSMenu (im_lazy) +-(id ) addItemWithTitle: (NSString *)s; +-(id ) addItemWithTitle: (NSString *)s action: (SEL)sel; +@end + +@interface EOModel (foo) +-(void)setCreatesMutableObjects:(BOOL)flag; +@end + +@implementation NSMenu (im_lazy) +-(id ) addItemWithTitle: (NSString *)s +{ + return [self addItemWithTitle: s action: NULL keyEquivalent: nil]; +} + +-(id ) addItemWithTitle: (NSString *)s action: (SEL)sel +{ + return [self addItemWithTitle: s action: sel keyEquivalent: nil]; +} +@end + + +@implementation Modeler +-(void)bundleDidLoad:(NSNotification *)not +{ + /* a place to put breakpoints? */ +} + +- (void) applicationWillFinishLaunching:(NSNotification *)not +{ + int i,c; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSArray *bundlesToLoad = RETAIN([defaults arrayForKey: @"BundlesToLoad"]); + NSMenu *mainMenu,*subMenu; + NSFileManager *fm = [NSFileManager defaultManager]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(bundleDidLoad:) + name:NSBundleDidLoadNotification + object:nil]; + for (i=0, c = [bundlesToLoad count]; i < c; i++) + { + BOOL isDir; + NSString *path = [[bundlesToLoad objectAtIndex:i] stringByExpandingTildeInPath]; + + [fm fileExistsAtPath:path isDirectory:&isDir]; + if (isDir) + { + NSLog(@"loading bundle: %@",path); + + [[[NSBundle bundleWithPath: path] principalClass] class]; //call class so +initialize gets called + } + } + RELEASE(bundlesToLoad); + + /* useful method for setting breakpoints after an adaptor is loaded */ + + mainMenu = [[NSMenu alloc] init]; + subMenu = [[NSMenu alloc] init]; + + [subMenu addItemWithTitle: _(@"Info..") + action: @selector(:orderFrontStandardInfoPanel:)]; + + [subMenu addItemWithTitle: _(@"Preferences...") + action: @selector(openPrefs:)]; + + [mainMenu setSubmenu: subMenu forItem: [mainMenu addItemWithTitle: _(@"Info")]]; + [subMenu release]; + subMenu = [[NSMenu alloc] init]; + + [subMenu addItemWithTitle: _(@"New...") + action: @selector(new:) + keyEquivalent: @"n"]; + + [subMenu addItemWithTitle: _(@"Open") + action: @selector(open:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Save") + action: @selector(save:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Save As") + action: @selector(saveAs:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Revert") + action: @selector(revert:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Set Adaptor Info") + action: @selector(setAdaptor:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Switch Adaptor") + action: @selector(switchAdaptor:) + keyEquivalent: @""]; + + [subMenu addItemWithTitle: _(@"Check consistency") + action: @selector(checkConsistency:) + keyEquivalent: @""]; + + [mainMenu setSubmenu: subMenu forItem: [mainMenu addItemWithTitle:_(@"Model")]]; + [subMenu release]; + + + subMenu = [[NSMenu alloc] init]; + [subMenu addItemWithTitle:_(@"Inspector") + action: @selector(showInspector:) + keyEquivalent: @"i"]; + [mainMenu setSubmenu:subMenu forItem:[mainMenu addItemWithTitle:_(@"Tools")]]; + [subMenu release]; + + subMenu = [[NSMenu alloc] init]; + [subMenu addItemWithTitle: _(@"Add entity") + action: @selector(addEntity:) + keyEquivalent: @"e"]; + + [subMenu addItemWithTitle: _(@"Add attribute") + action: @selector(addAttribute:) + keyEquivalent: @"a"]; + + [subMenu addItemWithTitle: _(@"Add relationship") + action: @selector(addRelationship:) + keyEquivalent: @"r"]; + + [mainMenu setSubmenu:subMenu forItem:[mainMenu addItemWithTitle:_(@"Property")]]; + [subMenu release]; + + [mainMenu addItemWithTitle: _(@"Hide") + action: @selector(hide:) + keyEquivalent: @"h"]; + + [mainMenu addItemWithTitle: _(@"Quit...") + action: @selector(terminate:) + keyEquivalent: @"q"]; + + [NSApp setMainMenu: mainMenu]; + /* make this a bundle? */ + [EOModelerDocument setDefaultEditorClass: NSClassFromString(@"MainModelEditor")]; + [[mainMenu window] makeKeyAndOrderFront:self]; +} + +- (void)new:(id)sender +{ + /* this entire function -really- seems to belong somewhere else */ + EOModelerCompoundEditor *editor; + EOModelerDocument *newModelerDoc; + EOModel *newModel = [[EOModel alloc] init]; + EOAdaptor *newAdaptor; + NSString *modelName; + unsigned int nDocs; + + //[newModel setCreateMutableObjects:YES]; + nDocs = [[EOMApp documents] count]; + + modelName=[NSString stringWithFormat:@"Model_%u",++nDocs]; + [newModel setName:modelName]; + [[EOModelGroup defaultGroup] addModel:newModel]; + + newModelerDoc = [[EOModelerDocument alloc] initWithModel: newModel]; + editor = (EOModelerCompoundEditor*)[newModelerDoc addDefaultEditor]; + [EOMApp setCurrentEditor: editor]; + [EOMApp addDocument: newModelerDoc]; + [newModelerDoc activate]; +} + +- (void) setAdaptor:(id)sender +{ + NSString *adaptorName; + EOAdaptor *adaptor; + AdaptorsPanel *adaptorsPanel = [[AdaptorsPanel alloc] init]; + + adaptorName = [adaptorsPanel runAdaptorsPanel]; + RELEASE(adaptorsPanel); + [[[EOMApp activeDocument] model] setAdaptorName: adaptorName]; + adaptor = [EOAdaptor adaptorWithName: adaptorName]; + [[[EOMApp activeDocument] model] setConnectionDictionary:[adaptor runLoginPanel]]; + +} + +- (void) showInspector:(id)sender +{ + [EOMInspectorController showInspector]; +} + +- (void) open:(id)sender +{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + if ([panel runModalForTypes:[NSArray arrayWithObject:@"eomodeld"]] == NSOKButton) + { + NSArray *modelPaths = [panel filenames]; + int i,c; + + for (i = 0, c = [modelPaths count]; i < c; i++) + { + NSString *modelPath = [modelPaths objectAtIndex:i]; + EOModel *model = [[EOModel alloc] initWithContentsOfFile:modelPath]; + EOModelerDocument *newDoc = [[EOModelerDocument alloc] initWithModel:model]; + EOModelerEditor *editor = (EOModelerCompoundEditor*)[newDoc addDefaultEditor]; + [EOMApp setCurrentEditor: editor]; + [EOMApp addDocument: newDoc]; + [newDoc activate]; + } + } +} +@end + diff --git a/DBModeler/ModelerAttributeEditor.h b/DBModeler/ModelerAttributeEditor.h new file mode 100644 index 0000000..99f2724 --- /dev/null +++ b/DBModeler/ModelerAttributeEditor.h @@ -0,0 +1,49 @@ +#ifndef __ModelerAttributeEditor_H_ +#define __ModelerAttributeEditor_H_ + +/* + ModelerAttributeEditor.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ModelerTableEmbedibleEditor.h" +#include + +@class NSSplitView; +@class NSTableView; +@class EODisplayGroup; +@class PlusMinusView; + +@interface ModelerAttributeEditor : ModelerTableEmbedibleEditor +{ + NSSplitView *_mainView; + NSTableView *_attributes_tableView; + NSTableView *_relationships_tableView; + EODisplayGroup *_attributes_dg; + EODisplayGroup *_relationships_dg; + id _entityToObserve; + id _attributeToObserve; +} + +@end + +#endif // __ModelerAttributeEditor_H_ + diff --git a/DBModeler/ModelerAttributeEditor.m b/DBModeler/ModelerAttributeEditor.m new file mode 100644 index 0000000..63a082a --- /dev/null +++ b/DBModeler/ModelerAttributeEditor.m @@ -0,0 +1,252 @@ +/** + ModelerAttributeEditor.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include "DefaultColumnProvider.h" +#include "ModelerAttributeEditor.h" +#include "ModelerEntityEditor.h" +#include "KVDataSource.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + + +@interface NSArray (EOMAdditions) +- (id) firstSelectionOfClass:(Class) aClass; +@end +@implementation ModelerAttributeEditor + +- (id) initWithParentEditor:(id)parentEditor +{ + NSScrollView *scrollView; + KVDataSource *wds1, *wds2; + int i,c; + NSPopUpButton *cornerView; + NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle:@"+" action:(SEL)nil keyEquivalent:@""]; + NSArray *columnNames; + + self = [super initWithParentEditor:parentEditor]; + [DefaultColumnProvider class]; + _mainView = [[NSSplitView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + /* setup the attributes table view */ + scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + _attributes_tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + [_attributes_tableView setAutoresizesAllColumnsToFit:YES]; + [scrollView setBorderType: NSBezelBorder]; + [scrollView setHasHorizontalScroller:YES]; + [scrollView setHasVerticalScroller:YES]; + [scrollView setDocumentView:_attributes_tableView]; + RELEASE(_attributes_tableView); + [_mainView addSubview:scrollView]; + RELEASE(scrollView); + + /* and the tableViews corner view */ + cornerView = [[NSPopUpButton alloc] initWithFrame:[[_attributes_tableView cornerView] bounds] pullsDown:YES]; + [[cornerView cell] setArrowPosition:NSPopUpNoArrow]; + [cornerView setTitle:@"+"]; + [cornerView setPreferredEdge:NSMinYEdge]; + + [[cornerView cell] setUsesItemFromMenu:NO]; + [[cornerView cell] setShowsFirstResponder:NO]; + [[cornerView cell] setMenuItem:mi]; + + [_attributes_tableView setCornerView:cornerView]; + RELEASE(cornerView); + + /* and the attributes tableview's display group */ + wds1 = [[KVDataSource alloc] initWithClassDescription:nil + editingContext:[[self document] editingContext]]; + [wds1 setKey:@"attributes"]; + _attributes_dg = [[EODisplayGroup alloc] init]; + [_attributes_dg setDataSource:wds1]; + RELEASE(wds1); + [_attributes_dg setFetchesOnLoad:YES]; + [_attributes_dg setDelegate:self]; + + [self setupCornerView:cornerView + tableView:_attributes_tableView + displayGroup:_attributes_dg + forClass:[EOAttribute class]]; + [self addDefaultTableColumnsForTableView:_attributes_tableView + displayGroup:_attributes_dg]; + + /* setup the relationships table view */ + scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + [scrollView setBorderType: NSBezelBorder]; + [scrollView setHasHorizontalScroller:YES]; + [scrollView setHasVerticalScroller:YES]; + _relationships_tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + [_relationships_tableView setAutoresizesAllColumnsToFit:YES]; + [scrollView setDocumentView:_relationships_tableView]; + RELEASE(_relationships_tableView); + [_mainView addSubview:scrollView]; + RELEASE(scrollView); + + /* and the tableViews corner view */ + cornerView = [[NSPopUpButton alloc] initWithFrame:[[_relationships_tableView cornerView] bounds] pullsDown:YES]; + [cornerView setPreferredEdge:NSMinYEdge]; + [[cornerView cell] setArrowPosition:NSPopUpNoArrow]; + [cornerView setTitle:@"+"]; + [[cornerView cell] setUsesItemFromMenu:NO]; + [[cornerView cell] setShowsFirstResponder:NO]; + [[cornerView cell] setMenuItem:mi]; + + [_relationships_tableView setCornerView:cornerView]; + RELEASE(cornerView); + /* and the relationships display group. */ + wds2 = [[KVDataSource alloc] initWithClassDescription:nil + editingContext:[[self document] editingContext]]; + [wds2 setKey:@"relationships"]; + _relationships_dg = [[EODisplayGroup alloc] init]; + [_relationships_dg setDataSource:wds2]; + RELEASE(wds2); + [_relationships_dg setFetchesOnLoad:YES]; + [_relationships_dg setDelegate:self]; + + [self setupCornerView:cornerView + tableView:_relationships_tableView + displayGroup:_relationships_dg + forClass:[EORelationship class]]; + + [self addDefaultTableColumnsForTableView:_relationships_tableView + displayGroup:_relationships_dg]; + + return self; +} + +- (void) dealloc +{ + if (_entityToObserve) + [EOObserverCenter removeObserver:self forObject:_entityToObserve]; + if (_attributeToObserve) + [EOObserverCenter removeObserver:self forObject:_attributeToObserve]; + RELEASE(_mainView); + RELEASE(_relationships_dg); + RELEASE(_attributes_dg); +} + +- (NSView *)mainView +{ + return _mainView; +} + +- (BOOL) canSupportCurrentSelection +{ + id selection = [self selectionWithinViewedObject]; + BOOL flag; + + if ([selection count] == 0) + return NO; + selection = [selection objectAtIndex:0]; + flag = ([selection isKindOfClass:[EOEntity class]] + || [selection isKindOfClass:[EORelationship class]]); + return flag; +} + + +- (void) activate +{ + if (_entityToObserve) + [EOObserverCenter removeObserver:self forObject:_entityToObserve]; + + _entityToObserve = [[self selectionPath] firstSelectionOfClass:[EOEntity class]]; + [EOObserverCenter addObserver:self forObject:_entityToObserve]; + + [(KVDataSource *)[_attributes_dg dataSource] setDataObject: _entityToObserve]; + [(KVDataSource *)[_relationships_dg dataSource] setDataObject: _entityToObserve]; + [_attributes_dg fetch]; + [_relationships_dg fetch]; +} + +- (NSArray *) friendEditorClasses +{ + return [NSArray arrayWithObjects: [ModelerEntityEditor class], nil]; +} + +- (void) objectWillChange:(id)sender +{ + [[NSRunLoop currentRunLoop] performSelector:@selector(needToFetch:) + target:self + argument:nil + order:999 + modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; +} + +- (void) needToFetch:(id)arg +{ + [_attributes_dg fetch]; + [_relationships_dg fetch]; +} + +- (NSArray *)defaultColumnNamesForClass:(Class)aClass +{ + NSArray *colNames = [super defaultColumnNamesForClass:aClass]; + if (colNames == nil || [colNames count] == 0) + { + if (aClass == [EOAttribute class]) + return DefaultAttributeColumns; + else if (aClass == [EORelationship class]) + return DefaultRelationshipColumns; + else + return nil; + } + + return colNames; +} + +- (void) displayGroupDidChangeSelection:(EODisplayGroup *)displayGroup +{ + NSArray *currentSelection = [_parentEditor selectionWithinViewedObject]; + id theSelection; + int c = [currentSelection count]; + if (c && c == 1 ) + theSelection = [currentSelection objectAtIndex:0]; + + if ([theSelection isKindOfClass:[EOEntity class]]) + { + NSArray *vop; + vop = [_parentEditor viewedObjectPath]; + [self setViewedObjectPath: [vop arrayByAddingObject:theSelection]]; + } + + [self setSelectionWithinViewedObject: [displayGroup selectedObjects]]; +} + +@end + diff --git a/DBModeler/ModelerEntityEditor.h b/DBModeler/ModelerEntityEditor.h new file mode 100644 index 0000000..9f1088e --- /dev/null +++ b/DBModeler/ModelerEntityEditor.h @@ -0,0 +1,54 @@ +#ifndef __ModelerEntityEditor_H_ +#define __ModelerEntityEditor_H_ + +/* + ModelerEntityEditor.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ModelerTableEmbedibleEditor.h" + +#include + +@class NSBox; +@class NSWindow; +@class NSTableView; +@class NSSplitView; +@class EODisplayGroup; +@class PlusMinusView; + +@interface ModelerEntityEditor : ModelerTableEmbedibleEditor +{ + NSTableView *_topTable; + NSTableView *_bottomTable; + NSSplitView *_splitView; + NSWindow *_window; + NSBox *_box; + EODisplayGroup *dg; +} + + +-(void)objectWillChange:(id)anObject; + +@end + +#endif // __ModelerEntityEditor_H_ + diff --git a/DBModeler/ModelerEntityEditor.m b/DBModeler/ModelerEntityEditor.m new file mode 100644 index 0000000..1b8713f --- /dev/null +++ b/DBModeler/ModelerEntityEditor.m @@ -0,0 +1,202 @@ +/** + ModelerEntityEditor.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include "DefaultColumnProvider.h" +#include "ModelerAttributeEditor.h" +#include "ModelerEntityEditor.h" +#include "KVDataSource.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +@interface EOModelerDocument (asdf) +-(void)_setDisplayGroup:(id)displayGroup; +@end + +@interface ModelerEntityEditor (Private) +- (void) _loadColumnsForClass:(Class) aClass; +@end + +@implementation ModelerEntityEditor + +- (BOOL) canSupportCurrentSelection +{ + id selection = [self selectionWithinViewedObject]; + BOOL flag; + + if ([selection count] == 0) + { + flag = NO; + return flag; + } + selection = [selection objectAtIndex:0]; + flag = [selection isKindOfClass:[EOModel class]]; + //NSLog(@"%@ %@ %i", [self class], NSStringFromSelector(_cmd), flag); + return flag; +} + +- (NSArray *) friendEditorClasses +{ + return [NSArray arrayWithObjects: [ModelerAttributeEditor class], nil]; +} + +- (id) initWithParentEditor: (EOModelerCompoundEditor *)parentEditor +{ + if (self = [super initWithParentEditor:parentEditor]) + { + id columnProvider; + NSTableColumn *tc; + EOClassDescription *classDescription = nil; + KVDataSource *wds; + NSArray *columnNames; + int i; + Class editorClass = [EOEntity class]; + NSScrollView *scrollView; + NSPopUpButton *cornerView; + NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle:@"+" action:(SEL)nil keyEquivalent:@""]; + + _splitView = [[NSSplitView alloc] initWithFrame:NSMakeRect(0,0,10,10)]; + scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,10,10)]; + [scrollView setHasHorizontalScroller:YES]; + [scrollView setHasVerticalScroller:YES]; + [scrollView setBorderType: NSBezelBorder]; + + _topTable = [[NSTableView alloc] initWithFrame:NSMakeRect(0,0,10,10)]; + _bottomTable = [[NSTableView alloc] initWithFrame:NSMakeRect(0,0,10,10)]; + [_topTable setAutoresizesAllColumnsToFit:YES]; + [scrollView setDocumentView:_topTable]; + [_splitView addSubview:scrollView]; + + scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,10,10)]; + [scrollView setHasHorizontalScroller:YES]; + [scrollView setHasVerticalScroller:YES]; + [scrollView setBorderType: NSBezelBorder]; + [_bottomTable setAutoresizesAllColumnsToFit:YES]; + [scrollView setDocumentView:_bottomTable]; + [_splitView addSubview:scrollView]; + + [DefaultColumnProvider class]; // calls +initialize + + cornerView = [[NSPopUpButton alloc] initWithFrame:[[_topTable cornerView] bounds] pullsDown:YES]; + [cornerView setPreferredEdge:NSMinYEdge]; + [cornerView setTitle:@"+"]; + [[cornerView cell] setArrowPosition:NSPopUpNoArrow]; + //[mi setImage:[NSImage imageNamed:@"plus"]]; + // [mi setOnStateImage:[NSImage imageNamed:@"plus"]]; + // [mi setOffStateImage:[NSImage imageNamed:@"plus"]]; + //[mi setState:NSOnState]; + [[cornerView cell] setUsesItemFromMenu:NO]; + [[cornerView cell] setShowsFirstResponder:NO]; + [[cornerView cell] setShowsStateBy:NSContentsCellMask]; + [[cornerView cell] setMenuItem:mi]; + [[cornerView cell] setImagePosition:NSNoImage]; + + [_topTable setCornerView:cornerView]; + RELEASE(cornerView); + [_topTable setAllowsMultipleSelection:YES]; + + classDescription = nil; + wds = [[KVDataSource alloc] + initWithClassDescription:classDescription + editingContext:[[self document] editingContext]]; + + [wds setDataObject: [[self document] model]]; + [wds setKey:@"entities"]; + dg = [[EODisplayGroup alloc] init]; + [EOObserverCenter addObserver:self forObject:[[self document] model]]; + [dg setDataSource: wds]; + [dg setFetchesOnLoad:YES]; + [dg setDelegate: self]; + + [self setupCornerView:cornerView + tableView:_topTable + displayGroup:dg + forClass:[EOEntity class]]; + + [self addDefaultTableColumnsForTableView:_topTable + displayGroup:dg]; + + + } + return self; +} +- (NSArray *)defaultColumnNamesForClass:(Class)aClass +{ + NSArray *colNames = [super defaultColumnNamesForClass:aClass]; + if (colNames == nil || [colNames count] == 0) + { + if (aClass == [EOEntity class]) + return DefaultEntityColumns; + else return nil; + } + + return colNames; +} + +- (void) activate +{ + [dg fetch]; +} + +- (NSView *)mainView +{ + return _splitView; +} + +- (void) objectWillChange:(id)anObject +{ + [[NSRunLoop currentRunLoop] performSelector:@selector(needToFetch:) target:self argument:nil order:999 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; +} + +- (void) needToFetch:(id)sth +{ + [dg fetch]; + [_topTable reloadData]; +} +@end + +@implementation ModelerEntityEditor (DisplayGroupDelegate) +- (void) displayGroupDidChangeSelection:(EODisplayGroup *)displayGroup +{ + //NSLog(@"didChangeSelection %@ %@",dg,[dg selectedObjects]); + [self setSelectionWithinViewedObject: [displayGroup selectedObjects]]; +} + +@end + diff --git a/DBModeler/ModelerTableEmbedibleEditor.h b/DBModeler/ModelerTableEmbedibleEditor.h new file mode 100644 index 0000000..cbbe649 --- /dev/null +++ b/DBModeler/ModelerTableEmbedibleEditor.h @@ -0,0 +1,53 @@ +#ifndef __ModelerTableEmbedibleEditor_H__ +#define __ModelerTableEmbedibleEditor_H__ + +/* + ModelerTableEmbedibleEditor.h + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +@class EODisplayGroup; +@class NSPopUpButton; +@class NSTableView; +/* base class for the default embedible editors + * mostly takes care of corner views right now.. + */ +@interface ModelerTableEmbedibleEditor : EOModelerEmbedibleEditor + +- (void) setupCornerView:(NSPopUpButton *)cornerView + tableView:(NSTableView *)tableView + displayGroup:(EODisplayGroup *)dg + forClass:(Class)aClass; + +- (void) _cornerAction:(id)sender; +- (NSArray *)defaultColumnNamesForClass:(Class)aClass; +- (void) addDefaultTableColumnsForTableView:(NSTableView *)tv + displayGroup:(EODisplayGroup *)dg; +- (void) addTableColumnForItem:(NSMenuItem *)item + tableView:(NSTableView *)tv; +- (void) removeTableColumnForItem:(NSMenuItem *)menuItem + tableView:(NSTableView *)tv; + +@end + +#endif // __ModelerTableEmbedibleEditor_H__ diff --git a/DBModeler/ModelerTableEmbedibleEditor.m b/DBModeler/ModelerTableEmbedibleEditor.m new file mode 100644 index 0000000..8c7c954 --- /dev/null +++ b/DBModeler/ModelerTableEmbedibleEditor.m @@ -0,0 +1,149 @@ +/** + ModelerTableEmbedibleEditor.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include "ModelerTableEmbedibleEditor.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "EOModeler/EOModelerApp.h" +/* base class with some methods shared among default embedible editors */ +@implementation ModelerTableEmbedibleEditor : EOModelerEmbedibleEditor +- (void) setupCornerView:(NSPopUpButton *)cornerView + tableView:(NSTableView *)tableView + displayGroup:(EODisplayGroup *)dg + forClass:(Class)aClass +{ + NSArray *columnNames = [EOMApp columnNamesForClass:aClass]; + int i, c; + [cornerView setTarget:self]; + [cornerView setAction:@selector(_cornerAction:)]; + [[cornerView cell] setRepresentedObject: aClass]; + + for (i = 0, c = [columnNames count]; i < c; i++) + { + NSString *columnName = [columnNames objectAtIndex:i]; + NSMenuItem *item; + + [cornerView addItemWithTitle:columnName]; + item = (NSMenuItem *)[cornerView itemWithTitle:columnName]; + [item setOnStateImage:[NSImage imageNamed:@"common_2DCheckMark"]]; + [item setState:NSOffState]; + } +} + +/* attempts to find column names from the defaults. + * subclasses should call supers, and return their default columns. + * if it returns nil or an array of count 0 */ +- (NSArray *)defaultColumnNamesForClass:(Class)aClass +{ + return [[[NSUserDefaults standardUserDefaults] dictionaryForKey:NSStringFromClass(aClass)] objectForKey:@"Columns"]; +} + +- (void) addDefaultTableColumnsForTableView:(NSTableView *)tv + displayGroup:(EODisplayGroup *)dg +{ + Class aClass = [[(NSPopUpButton*)[tv cornerView] cell] representedObject]; + NSArray *columnNames = [self defaultColumnNamesForClass:aClass]; + int i, c; + for (i = 0, c = [columnNames count]; i < c; i++) + { + NSString *columnName = [columnNames objectAtIndex:i]; + NSPopUpButton *cv = [tv cornerView]; + NSMenuItem *item; + id provider; + NSTableColumn *tc = [[NSTableColumn alloc] initWithIdentifier:nil]; + + provider = [EOMApp providerForName: columnName class:aClass]; + + /* THIS *MUST* be before initColumn:class:name:displayGroup:document calls */ + [tv addTableColumn:tc]; + + [provider initColumn:tc class:aClass name:columnName + displayGroup:dg document:[self document]]; + + item = (NSMenuItem *)[cv itemWithTitle:columnName]; + [item setRepresentedObject:tc]; + [item setState:NSOnState]; + } + [tv sizeToFit]; +} + +- (void) addTableColumnForItem:(NSMenuItem *)item + tableView:(NSTableView *)tv +{ + NSString *columnName = [item title]; + Class aClass = [[(NSPopUpButton *)[tv cornerView] cell] representedObject]; + id provider = [EOMApp providerForName:columnName class:aClass]; + NSTableColumn *tc = [[NSTableColumn alloc] initWithIdentifier:nil]; // can't rely on ident. + + [item setState:NSOnState]; + [item setRepresentedObject:tc]; + + /* THIS *MUST* be before initColumn:class:name:displayGroup:document calls */ + [tv addTableColumn:tc]; + + /* this requires that the table at least have 1 table column in it... + * so we have to have another method to setup the default table columns */ + [provider initColumn:tc + class:aClass + name:columnName + displayGroup:[[tv delegate] displayGroupForAspect:@"source"] // <-+-^ + document:[self document]]; + + [tv sizeToFit]; +} + +- (void) removeTableColumnForItem:(NSMenuItem *)item + tableView:(NSTableView *)tv +{ + [tv removeTableColumn:[item representedObject]]; + [item setRepresentedObject:nil]; + [item setState:NSOffState]; +} + +- (void) _cornerAction:(id)sender +{ + NSMenuItem *item = (NSMenuItem*)[sender selectedItem]; + NSTableView *tv = [[sender enclosingScrollView] documentView]; + if ([item state] == NSOnState) + { + [self removeTableColumnForItem:item tableView:tv]; + } + else + { + [self addTableColumnForItem:item tableView:tv]; + } +} + +@end + diff --git a/DBModeler/Resources/ClassProperty_On.tiff b/DBModeler/Resources/ClassProperty_On.tiff new file mode 100644 index 0000000..b91f10e Binary files /dev/null and b/DBModeler/Resources/ClassProperty_On.tiff differ diff --git a/DBModeler/Resources/Key_On.tiff b/DBModeler/Resources/Key_On.tiff new file mode 100644 index 0000000..6d3d9c5 Binary files /dev/null and b/DBModeler/Resources/Key_On.tiff differ diff --git a/DBModeler/Resources/ModelDrag.tiff b/DBModeler/Resources/ModelDrag.tiff new file mode 100644 index 0000000..b7fddd0 Binary files /dev/null and b/DBModeler/Resources/ModelDrag.tiff differ diff --git a/DBModeler/main.m b/DBModeler/main.m new file mode 100644 index 0000000..8845654 --- /dev/null +++ b/DBModeler/main.m @@ -0,0 +1,40 @@ +/** + main.m + + Author: Matt Rice + Date: Apr 2005 + + This file is part of DBModeler. + + + DBModeler is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DBModeler is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DBModeler; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +**/ + + +#include +#include +#include "Modeler.h" + +int main (int argc, const char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + [EOModelerApp sharedApplication]; + [NSApp setDelegate: [[Modeler alloc] init]]; + [NSApp run]; + RELEASE(pool); + return 0; +} diff --git a/GDL2Palette/ConnectionInspector.h b/GDL2Palette/ConnectionInspector.h new file mode 100644 index 0000000..2cc13eb --- /dev/null +++ b/GDL2Palette/ConnectionInspector.h @@ -0,0 +1,27 @@ +#include +@class NSBrowser; +@class NSPopUpButton; + +@interface GDL2ConnectionInspector : IBInspector +{ + NSBrowser *oaBrowser; + NSBrowser *connectionsBrowser; + NSPopUpButton *popUp; + + NSArray *_keys; + NSArray *_signatures; + NSArray *_values; + NSMutableArray *_connectors; + + NSNibConnector *_currentConnector; + +} + +- (void) updateKeys; +- (void) updateValues; +- (void) updateButtons; +- (void) selectedConnector; +- (void) selectedOutletOrAction; +@end + + diff --git a/GDL2Palette/ConnectionInspector.m b/GDL2Palette/ConnectionInspector.m new file mode 100644 index 0000000..81dbd04 --- /dev/null +++ b/GDL2Palette/ConnectionInspector.m @@ -0,0 +1,572 @@ +#include "ConnectionInspector.h" +#include "Foundation+Categories.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include +/* TODO get notifications for IB{Will,Did}RemoveConnectorNotification + * and remove the object from the _objectToAssociation map table if + * there are no more connectors for it */ +static NSMapTable *_objectToAssociation; + +@interface NSApplication(missingStuff) +- (GormClassManager *)classManager; +@end + +@implementation GDL2ConnectionInspector ++ (void) initialize +{ + _objectToAssociation = NSCreateMapTableWithZone(NSObjectMapKeyCallBacks, + NSObjectMapValueCallBacks, + 0, [self zone]); +} + +- (NSButton *)okButton +{ + return nil; +} + +- (id) init +{ + self = [super init]; + + [NSBundle loadNibNamed:@"GDL2ConnectionInspector" owner:self]; + return self; +} + +- (void) awakeFromNib +{ + [oaBrowser setMaxVisibleColumns:2]; + [oaBrowser setAllowsMultipleSelection:NO]; + [oaBrowser setHasHorizontalScroller:NO]; + [oaBrowser setTitled:NO]; + + [connectionsBrowser setTitled:NO]; + [connectionsBrowser setHasHorizontalScroller:NO]; + [connectionsBrowser setMaxVisibleColumns:1]; + [connectionsBrowser setAllowsMultipleSelection:NO]; + + [popUp removeAllItems]; + +} + +- (void) setObject:(id)anObject +{ + NSArray *foo; + int i,c; + + [super setObject:anObject]; + + if (!object) return; + + RELEASE(_connectors); + _connectors = [NSMutableArray new]; + + [_connectors addObjectsFromArray:[[[(id)NSApp activeDocument] + connectorsForSource:object] + arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClasses:) + withObject:[NSArray arrayWithObjects:[NSNibControlConnector class], + [NSNibOutletConnector class], + [EOAspectConnector class], + nil]]]; + + DESTROY(_values); + [self updateKeys]; + [popUp removeAllItems]; + [popUp addItemWithTitle:@"Outlets"]; + + foo = RETAIN([EOAssociation associationClassesForObject:anObject]); + for (i = 0, c = [foo count]; i < c; i++) + { + Class assocSubclass = [foo objectAtIndex:i]; + NSString *title = [assocSubclass displayName]; + [popUp addItemWithTitle:title]; + [[popUp itemWithTitle:title] setRepresentedObject:assocSubclass]; + } + RELEASE(foo); + [connectionsBrowser reloadColumn:0]; + [oaBrowser loadColumnZero]; + [self updateButtons]; +} + +- (void) _popUpAction:(id)sender +{ + [self updateKeys]; + [oaBrowser reloadColumn:0]; + [oaBrowser reloadColumn:1]; + [connectionsBrowser reloadColumn:0]; +} + +- (void) updateKeys +{ + Class repObj = [[popUp selectedItem] representedObject]; + RELEASE(_keys); + RELEASE(_signatures); + + /* outlets.. */ + if (repObj == nil) + { + _keys = RETAIN([[NSApp classManager] allOutletsForObject:object]); + _signatures = nil; + } + else + { + _keys = RETAIN([repObj aspects]); + _signatures = RETAIN([repObj aspectSignatures]); + } +} + +- (void) updateValues +{ + id dest = [NSApp connectDestination]; + int selection = [oaBrowser selectedRowInColumn:0]; + NSString *sig = [_signatures objectAtIndex:selection]; + NSMutableArray *objs = [NSMutableArray new]; + EOEntity *ent = nil; + + sig = [sig uppercaseString]; + if ([dest isKindOfClass:[EODisplayGroup class]]) + ent = [(EODatabaseDataSource *)[(EODisplayGroup *)dest dataSource] entity]; + if ([sig length] && ent) + { + int i,c; + for (i = 0, c = [sig length]; i < c; i++) + { + switch ([sig characterAtIndex:i]) + { + case 'A': + [objs addObjectsFromArray: [ent classAttributes]]; + break; + case '1': + [objs addObjectsFromArray: [ent classToOneRelationships]]; + break; + case 'M': + [objs addObjectsFromArray: [ent classToManyRelationships]]; + break; + } + } + } + RELEASE(_values); + _values = objs; + +} + +- (void) _selectAction:(NSString*)label +{ + [oaBrowser reloadColumn:1]; + if (label != nil) + [oaBrowser selectRow:[_values indexOfObject:label] inColumn:1]; +} + +- (void) _oaBrowserAction:(id)sender +{ + unsigned i,c; + NSNibConnector *conn; + + switch ([sender selectedColumn]) + { + case 0: + { + id dest; + + if ([[popUp selectedItem] representedObject] == nil) + { + if ([[[sender selectedCell] stringValue] isEqual:@"target"]) + { + NSArray *controlConnectors; + controlConnectors = [_connectors arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClass:) + withObject:[NSNibControlConnector class]]; + c = [controlConnectors count]; + conn = c ? [controlConnectors objectAtIndex:0] + : nil; + dest = c ? [conn destination] + : [NSApp connectDestination]; + RELEASE(_values); + _values = RETAIN([[NSApp classManager] allActionsForObject: dest]); + if ([_values count] > 0) + { + conn = [NSNibControlConnector new]; + [conn setSource: object]; + [conn setDestination: [NSApp connectDestination]]; + [conn setLabel: [_values objectAtIndex:0]]; + AUTORELEASE(conn); + } + if (_currentConnector != conn) + ASSIGN(_currentConnector, conn); + [self _selectAction: [conn label]]; + } + else + { + BOOL found = NO; + NSString *title = [[sender selectedCell] stringValue]; + NSArray *outletConnectors; + + outletConnectors = [_connectors arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClass:) + withObject:[NSNibOutletConnector class]]; + for (i = 0, c = [outletConnectors count]; i < c; i++) + { + conn = [outletConnectors objectAtIndex:i]; + if ([conn label] == nil || [[conn label] isEqual:title]) + { + found = YES; + ASSIGN(_currentConnector, conn); + break; + } + } + + if (!found) + { + RELEASE(_currentConnector); + _currentConnector = [NSNibOutletConnector new]; + [_currentConnector setSource:object]; + [_currentConnector setDestination:[NSApp connectDestination]]; + [_currentConnector setLabel:title]; + } + } + [connectionsBrowser loadColumnZero]; + [self selectedOutletOrAction]; + } + else /* association connector */ + { + [self updateValues]; + [oaBrowser reloadColumn:1]; + } + } + break; + case 1: + if ([[popUp selectedItem] representedObject] == nil) + { + BOOL found = NO; + NSString *title = [[sender selectedCell] stringValue]; + NSArray *controlConnectors; + + controlConnectors = [_connectors arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClass:) + withObject:[NSNibControlConnector class]]; + + for (i = 0, c = [controlConnectors count]; i < c; i++) + { + NSNibConnector *con = [controlConnectors objectAtIndex:i]; + NSString *action = [con label]; + if ([action isEqual:title]) + { + ASSIGN(_currentConnector, con); + found = YES; + break; + } + } + if (!found) + { + RELEASE(_currentConnector); + _currentConnector = [NSNibControlConnector new]; + [_currentConnector setSource:object]; + [_currentConnector setDestination:[NSApp connectDestination]]; + [_currentConnector setLabel:title]; + [connectionsBrowser loadColumnZero]; + } + [self selectedOutletOrAction]; + } + else + { + BOOL found = NO; + NSString *aspectName = [[sender selectedCellInColumn:0] stringValue]; + NSString *key = [[sender selectedCell] stringValue]; + NSString *label = [NSString stringWithFormat:@"%@ - %@", aspectName, key]; + NSArray *aspectConnectors; + + aspectConnectors = [_connectors arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClass:) + withObject:[EOAspectConnector class]]; + for (i = 0, c = [aspectConnectors count]; i < c; i++) + { + NSNibConnector *con = [aspectConnectors objectAtIndex:i]; + if ([con source] == object && [[con label] isEqual: label]) + { + ASSIGN(_currentConnector, con); + found = YES; + break; + } + } + if (!found) + { + EOAssociation *assoc; + + assoc = NSMapGet(_objectToAssociation, object); + + if (!assoc) + { + Class assocClass = [[popUp selectedItem] representedObject]; + assoc = [[assocClass alloc] initWithObject:object]; + NSMapInsert(_objectToAssociation, object, assoc); + } + + [assoc bindAspect:aspectName + displayGroup:[NSApp connectDestination] + key:key]; + + RELEASE(_currentConnector); + _currentConnector = [[EOAspectConnector alloc] + initWithAssociation:assoc + aspectName:aspectName]; + [_currentConnector setSource:object]; + [_currentConnector setDestination: [NSApp connectDestination]]; + [_currentConnector setLabel:label]; + } + } + break; + } + [self updateButtons]; +} + +- (void) selectedOutletOrAction +{ + NSString *path; + NSString *name = [[(id )NSApp activeDocument] nameForObject:[_currentConnector destination]]; + path = [@"/" stringByAppendingString:[_currentConnector label]]; + path = [path stringByAppendingFormat:@" (%@)", name]; + [connectionsBrowser setPath:path]; +} + +- (void) updateButtons +{ + + if (!_currentConnector) + { + [okButton setState: NSOffState]; + } + else + { + id src, dest; + id firstResponder = [(GormDocument *)[(id)NSApp activeDocument] firstResponder]; + src = [_currentConnector source]; + dest = [_currentConnector destination]; + if (src && src != firstResponder + && ((dest && dest != firstResponder) + || ![_currentConnector isKindOfClass:[NSNibOutletConnector class]])) + { + BOOL flag; + + flag = [_connectors containsObject:_currentConnector]; + [okButton setState: flag ? NSOnState : NSOffState]; + } + else + { + [okButton setState: NSOnState]; + } + } +} + +- (void) _connectionsBrowserAction:(id)sender +{ + int i,c; + NSNibConnector *con; + NSString *title = [[sender selectedCell] stringValue]; + BOOL found; + + for (i = 0, c = [_connectors count]; i < c; i++) + { + NSString *label; + + con = [_connectors objectAtIndex:i]; + + label = [con label]; + if (label == nil || [title hasPrefix:label]) + { + NSString *name; + id dest; + + dest = [con destination]; + name = [[(id )NSApp activeDocument] nameForObject:dest]; + name = [label stringByAppendingFormat: @" (%@)", name]; + if ([title isEqual:name]) + { + NSString *path; + + ASSIGN(_currentConnector, con); + [self selectedConnector]; + break; + } + } + } + [self updateButtons]; +} + +- (void) selectedConnector +{ + NSString *path; + + path = [@"/" stringByAppendingString:[_currentConnector label]]; + if ([_currentConnector isKindOfClass: [NSNibControlConnector class]]) + { + path = [@"/target" stringByAppendingString:path]; + } + [oaBrowser setPath:path]; + [NSApp displayConnectionBetween:object and:[_currentConnector destination]]; +} + +- (int) browser:(NSBrowser *)browser +numberOfRowsInColumn:(int)column +{ + id repObj = [[popUp selectedItem] representedObject]; + if (browser == oaBrowser) + switch(column) + { + case 0: + return [_keys count]; + break; + case 1: + if (repObj == nil) + { + if ([[[browser selectedCellInColumn:0] stringValue] isEqual:@"target"]) + { + return [_values count]; + } + else return 0; + } + else + { + return [_values count]; + } + break; + default: + [[NSException exceptionWithName:NSInternalInconsistencyException + reason:@"uhhhhh should be column 0 or 1...." + userInfo: nil] raise]; + return 0; + break; + } + else if (browser == connectionsBrowser) + return [_connectors count]; +} + +- (void) browser:(NSBrowser *)sender +willDisplayCell:(id)cell atRow:(int)row column:(int)column +{ + id repObj = [[popUp selectedItem] representedObject]; + if (sender == oaBrowser) + switch (column) + { + case 0: + if (repObj == nil) + { + NSString *name; + name = [_keys objectAtIndex:row]; + [cell setStringValue:name]; + [cell setLeaf: [name isEqual:@"target" ] ? NO : YES]; + [cell setEnabled:YES]; + } + else + { + [cell setStringValue: [_keys objectAtIndex:row]]; + [cell setLeaf:[[_signatures objectAtIndex:row] length] == 0]; + } + break; + case 1: + if (repObj == nil) + { + if ([[[sender selectedCellInColumn:0] stringValue] isEqual:@"target"]) + { + [cell setLeaf:YES]; + [cell setStringValue: [_values objectAtIndex:row]]; + [cell setEnabled:YES]; + } + } + else + { + [cell setLeaf:YES]; // TODO relationships should be NO... + [cell setStringValue: [(EOAttribute *)[_values objectAtIndex:row] name]]; + [cell setEnabled:YES]; + } + break; + } + else if (sender == connectionsBrowser) + { + int i, c; + NSNibConnector *conn; + NSString *name, *dest, *label; + + if (row < 0 || column != 0) return; + + conn = [_connectors objectAtIndex:row]; + label = [conn label]; + dest = [conn destination]; + name = [[(id)NSApp activeDocument] nameForObject: dest]; + [cell setStringValue: [label stringByAppendingFormat:@" (%@)", name]]; + [cell setEnabled:YES]; + [cell setLeaf:YES]; + } + +} + +- (void) ok:(id)sender +{ + if ([_currentConnector destination] == nil || + [_currentConnector source] == nil) + { + NSRunAlertPanel(_(@"Problem making connection"), + _(@"Please select a valid destination."), + _(@"OK"), nil, nil, nil); + } + else if ([_connectors containsObject:_currentConnector] == YES) + { + [[(id)NSApp activeDocument] removeConnector: _currentConnector]; +// [_currentConnector setDestination:nil]; +// [_currentConnector setLabel:nil]; + [_connectors removeObject:_currentConnector]; + [connectionsBrowser loadColumnZero]; + } + else + { + NSString *path; + id dest; + + if ([_currentConnector isKindOfClass:[NSNibControlConnector class]]) + { + int i, c; + NSArray *controlConnectors; + + controlConnectors = [_connectors arrayWithObjectsRespondingYesToSelector:@selector(isKindOfClass:) + withObject:[NSNibControlConnector class]]; + + for (i = 0, c = [controlConnectors count]; i < c; i++) + { + NSNibConnector *con = [controlConnectors objectAtIndex:i]; + [[(id)NSApp activeDocument] removeConnector: con]; + [_connectors removeObject:con]; + } + [_connectors addObject:_currentConnector]; + } + else if ([_currentConnector isKindOfClass:[NSNibOutletConnector class]]) + { + [_connectors addObject:_currentConnector]; + } + else if ([_currentConnector isKindOfClass:[EOAspectConnector class]]) + { + [_connectors addObject:_currentConnector]; + } + + [self _selectAction:[_currentConnector label]]; + [[(id)NSApp activeDocument] addConnector: _currentConnector]; + [connectionsBrowser loadColumnZero]; + [self selectedConnector]; + } + + [[(id)NSApp activeDocument] touch]; + [self updateButtons]; +} +@end + diff --git a/GDL2Palette/Foundation+Categories.h b/GDL2Palette/Foundation+Categories.h new file mode 100644 index 0000000..4c7d996 --- /dev/null +++ b/GDL2Palette/Foundation+Categories.h @@ -0,0 +1,11 @@ +#include +/* since we don't really have blocks and i don't feel like including them.. */ +@interface NSArray (SelectorStuff) +- (NSArray *) arrayWithObjectsRespondingYesToSelector:(SEL)selector; +- (NSArray *) arrayWithObjectsRespondingYesToSelector:(SEL)selector +withObject:(id)argument; +@end + +@interface NSObject(GDL2PaletteAdditions) +- (BOOL) isKindOfClasses:(NSArray *)classes; +@end diff --git a/GDL2Palette/Foundation+Categories.m b/GDL2Palette/Foundation+Categories.m new file mode 100644 index 0000000..0dc13af --- /dev/null +++ b/GDL2Palette/Foundation+Categories.m @@ -0,0 +1,74 @@ +#include "Foundation+Categories.h" + +/* since we don't really have blocks and i don't feel like including them.. */ +@implementation NSArray (GDL2PaletteAdditions) + +- (NSArray *) arrayWithObjectsRespondingYesToSelector:(SEL)selector; +{ + int i,c; + BOOL (*sel_imp)(id, SEL, ...); + NSMutableArray *arr = [[NSMutableArray alloc] init]; + BOOL flag; + + for (i = 0, c = [self count]; i < c; i++) + { + id obj = [self objectAtIndex:i]; + + flag = [obj respondsToSelector:selector]; + + if (flag) + { + sel_imp = (BOOL (*)(id, SEL, ...))[obj methodForSelector:selector]; + flag = (*sel_imp)(obj, selector); + + if (flag) + [arr addObject:obj]; + } + } + return arr; +} + +- (NSArray *) arrayWithObjectsRespondingYesToSelector:(SEL)selector +withObject:(id)argument; +{ + int i,c; + BOOL (*sel_imp)(id, SEL, ...); + NSMutableArray *arr = [[NSMutableArray alloc] init]; + BOOL flag; + + for (i = 0, c = [self count]; i < c; i++) + { + id obj = [self objectAtIndex:i]; + + flag = [obj respondsToSelector:selector]; + + if (flag) + { + sel_imp = (BOOL (*)(id, SEL, ...))[obj methodForSelector:selector]; + flag = (*sel_imp)(obj, selector, argument); + + if (flag) + [arr addObject:obj]; + } + } + return arr; +} + +@end + +@implementation NSObject(GDL2PaletteAdditions) +- (BOOL) isKindOfClasses:(NSArray *)classes +{ + int i,c; + BOOL flag; + + for (i = 0, c = [classes count]; i < c; i++) + { + if ([self isKindOfClass: [classes objectAtIndex:i]]) + return YES; + } + return NO; +} + +@end + diff --git a/GDL2Palette/GDL2ConnectionInspector.gorm/data.classes b/GDL2Palette/GDL2ConnectionInspector.gorm/data.classes new file mode 100644 index 0000000..3973f2f --- /dev/null +++ b/GDL2Palette/GDL2ConnectionInspector.gorm/data.classes @@ -0,0 +1,26 @@ +{ + "## Comment" = "Do NOT change this file, Gorm maintains it"; + FirstResponder = { + Actions = ( + "_connectionsBrowserAction:", + "_oaBrowserAction:", + "_popUpAction:" + ); + Super = NSObject; + }; + GDL2ConnectionInspector = { + Actions = ( + "_connectionsBrowserAction:", + "_oaBrowserAction:", + "_popUpAction:" + ); + Outlets = ( + oaBrowser, + revertButton, + okButton, + popUp, + connectionsBrowser + ); + Super = IBInspector; + }; +} \ No newline at end of file diff --git a/GDL2Palette/GDL2ConnectionInspector.gorm/data.info b/GDL2Palette/GDL2ConnectionInspector.gorm/data.info new file mode 100644 index 0000000..ca921cf Binary files /dev/null and b/GDL2Palette/GDL2ConnectionInspector.gorm/data.info differ diff --git a/GDL2Palette/GDL2ConnectionInspector.gorm/objects.gorm b/GDL2Palette/GDL2ConnectionInspector.gorm/objects.gorm new file mode 100644 index 0000000..86e2eef Binary files /dev/null and b/GDL2Palette/GDL2ConnectionInspector.gorm/objects.gorm differ diff --git a/GDL2Palette/GDL2Palette.tiff b/GDL2Palette/GDL2Palette.tiff new file mode 100644 index 0000000..50d447c Binary files /dev/null and b/GDL2Palette/GDL2Palette.tiff differ diff --git a/GDL2Palette/GNUmakefile b/GDL2Palette/GNUmakefile new file mode 100644 index 0000000..ac861e5 --- /dev/null +++ b/GDL2Palette/GNUmakefile @@ -0,0 +1,34 @@ +include $(GNUSTEP_MAKEFILES)/common.make +include $(GNUSTEP_MAKEFILES)/Auxiliary/gdl2.make + +PALETTE_NAME=GDL2 +GDL2_PRINCIPAL_CLASS = GDL2Palette + +ifeq ($(FOUNDATION_LIB),apple) + ADDITIONAL_INCLUDE_DIRS += -F../EOModeler -F../EOInterface + ADDITIONAL_LIB_DIRS += -F../EOModeler -F../EOInterface +else + ADDITIONAL_INCLUDE_DIRS += -I../ + ADDITIONAL_LIB_DIRS += -L../EOModeler -L../EOInterface +endif + +ADDITIONAL_NATIVE_LIBS+=EOModeler EOInterface +LDFLAGS+=-framework gnustep-db2modeler -framework EOInterface + + +ADDITIONAL_LIB_DIRS= \ +-L../EOAccess/$(GNUSTEP_OBJ_DIR) \ +-L../EOControl/$(GNUSTEP_OBJ_DIR) + +ADDITIONAL_LDFLAGS+=-lgnustep-db2control -lgnustep-db2 + +GDL2_RESOURCE_FILES=GDL2Palette.tiff GDL2ConnectionInspector.gorm palette.table + +GDL2_OBJC_FILES= \ + Palette.m \ + ResourceManager.m \ + ConnectionInspector.m \ + IB+Categories.m \ + Foundation+Categories.m + +include $(GNUSTEP_MAKEFILES)/palette.make diff --git a/GDL2Palette/IB+Categories.m b/GDL2Palette/IB+Categories.m new file mode 100644 index 0000000..95ceee1 --- /dev/null +++ b/GDL2Palette/IB+Categories.m @@ -0,0 +1,40 @@ +#include + +#include +@interface EODisplayGroup (PaletteStuff) +- (NSString *)connectInspectorClassName; +@end + +@implementation EODisplayGroup (PaletteStuff) +- (NSString *)connectInspectorClassName +{ + return @"GDL2ConnectionInspector"; +} +@end + +#include +@interface NSView (PaletteStuff) +- (NSString *)connectInspectorClassName; +@end + +@implementation NSView (PaletteStuff) +- (NSString *)connectInspectorClassName +{ + return @"GDL2ConnectionInspector"; +} +@end + +#include + +@interface NSTableColumn (PaletteStuff) +- (NSString *)connectInspectorClassName; +@end + +@implementation NSTableColumn (PaletteStuff) +- (NSString *)connectInspectorClassName +{ + return @"GDL2ConnectionInspector"; +} + +@end + diff --git a/GDL2Palette/Palette.h b/GDL2Palette/Palette.h new file mode 100644 index 0000000..2d6d0d7 --- /dev/null +++ b/GDL2Palette/Palette.h @@ -0,0 +1,9 @@ +#include + +@interface GDL2Palette : IBPalette +{ + +} + +@end + diff --git a/GDL2Palette/Palette.m b/GDL2Palette/Palette.m new file mode 100644 index 0000000..54d9138 --- /dev/null +++ b/GDL2Palette/Palette.m @@ -0,0 +1,13 @@ +#include "Palette.h" +#include "ResourceManager.h" + + +@implementation GDL2Palette + ++(void) initialize +{ +// NSLog(@"GDL2Palette initialize"); + [IBResourceManager registerResourceManagerClass:[GDL2ResourceManager class]]; +} + +@end diff --git a/GDL2Palette/ResourceManager.h b/GDL2Palette/ResourceManager.h new file mode 100644 index 0000000..e4c1d45 --- /dev/null +++ b/GDL2Palette/ResourceManager.h @@ -0,0 +1,14 @@ +#include + +@class EOEditingContext; +@class EOModelGroup; + + +@interface GDL2ResourceManager : IBResourceManager +{ + EOEditingContext *_defaultEditingContext; + EOModelGroup *modelGroup; +} + +@end + diff --git a/GDL2Palette/ResourceManager.m b/GDL2Palette/ResourceManager.m new file mode 100644 index 0000000..f33be43 --- /dev/null +++ b/GDL2Palette/ResourceManager.m @@ -0,0 +1,93 @@ +#include "ResourceManager.h" + +#include + +#include + +#include +#include + +#include + +#include +#include + +@implementation GDL2ResourceManager +- (id) initWithDocument:(id)doc +{ + self = [super initWithDocument:doc]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didOpenDocument:) + name:IBDidOpenDocumentNotification + object:[self document]]; + return self; +} + +- (void) didOpenDocument:(NSNotification *)notif +{ + NSArray *tmp; + NSMutableArray *modelPaths = [NSMutableArray new]; + NSString *docPath; + int i,c; + docPath = [[[self document] documentPath] stringByDeletingLastPathComponent]; + tmp = [[NSBundle bundleWithPath: docPath] + pathsForResourcesOfType:@"eomodeld" + inDirectory:nil]; + [modelPaths addObjectsFromArray:tmp]; + tmp = [[NSBundle bundleWithPath: docPath] + pathsForResourcesOfType:@"eomodel" + inDirectory:nil]; + + for (i = 0, c = [modelPaths count]; i < c; i++) + { + if (![[EOModelGroup defaultGroup] modelWithPath:[modelPaths objectAtIndex:i]]) + [[EOModelGroup globalModelGroup] + addModelWithFile:[modelPaths objectAtIndex:i]]; + } +} + +- (EOEditingContext *) defaultEditingContext +{ + if (!_defaultEditingContext) + _defaultEditingContext = [[EOEditingContext alloc] init]; + return _defaultEditingContext; +} + +- (BOOL) acceptsResourcesFromPasteboard:(NSPasteboard *)pb +{ + return [[pb types] containsObject:EOMPropertyPboardType]; +} + +- (NSArray *)resourcePasteboardTypes +{ + return [NSArray arrayWithObject: EOMPropertyPboardType]; +} + +- (void) addResourcesFromPasteboard:(NSPasteboard *)pb +{ + NSArray *pList = [pb propertyListForType:EOMPropertyPboardType]; + EODisplayGroup *dg = [[EODisplayGroup alloc] init]; + EOEditingContext *ec = [self defaultEditingContext]; + EODatabaseDataSource *ds; + NSString *modelPath = [pList objectAtIndex:0]; + + int i,c; + + if (![[self document] containsObject:ec]) + { + [[self document] attachObject:ec toParent:nil]; + } + + if (![[EOModelGroup defaultGroup] modelWithPath:modelPath]) + { + [[EOModelGroup defaultGroup] addModelWithFile:modelPath]; + } + ds = [[EODatabaseDataSource alloc] + initWithEditingContext:ec + entityName:[pList objectAtIndex:1]]; + [dg setDataSource:ds]; + [[self document] attachObject:dg toParent:nil]; +} + +@end + diff --git a/GDL2Palette/palette.table b/GDL2Palette/palette.table new file mode 100644 index 0000000..35f203f --- /dev/null +++ b/GDL2Palette/palette.table @@ -0,0 +1,8 @@ +{ + NOTE = "Automatically generated, do not edit!"; + NibFile = ""; + Class = "GDL2Palette"; + Icon = "GDL2Palette"; + ExportClasses = ("EODisplayGroup", "EOEditingContext"); +} +