Fix placement of auxiliary IM window for Core Text
[MacVim.git] / src / MacVim / PlugInImpl.m
blob8f272b78d6e632d2af73b62b24ac8883c2a7d233
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
12  * MMPlugInInstanceMediator
13  *
14  * Implementation of the PlugInInstanceMediator protocol.  One of these is
15  * created per vim instance.  It manages all of the plugin instances for that
16  * vim instance.
17  *
18  * MMPlugInAppMediator
19  *
20  * Implementation of the PlugInAppMediator protocol.  Singleton class.
21  *
22  * Author: Matt Tolton
23  */
25 #import "Miscellaneous.h"
27 #ifdef MM_ENABLE_PLUGINS
29 static int MMPlugInArchMajorVersion = 1;
30 static int MMPlugInArchMinorVersion = 0;
32 #import "PlugInImpl.h"
33 #import "PlugInGUI.h"
34 #import "MMPlugInManager.h"
35 #import "RBSplitView.h"
36 #import "MMAppController.h"
37 #import "MMVimController.h"
40 @implementation MMPlugInInstanceMediator
42 - (void)setupDrawer
44     // XXX The drawer does not work in full screen mode.  Eventually, the
45     // drawer will go away so I'm ignoring this issue for now.
46     drawer = [[NSDrawer alloc] initWithContentSize:NSMakeSize(200,100)
47                                      preferredEdge:NSMinXEdge];
50     NSSize contentSize = [drawer contentSize];
52     // XXX memory management for this
53     MMPlugInViewContainer *containerView = [[MMPlugInViewContainer alloc]
54         initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height)];
56     [drawer setContentView:containerView];
58     [containerView release];
60     [drawer setParentWindow:[[vimController windowController] window]];
63 - (void)toggleDrawer
65     [drawer toggle:nil];
66     [[NSUserDefaults standardUserDefaults]
67         setBool:[drawer state] == NSDrawerOpenState
68             || [drawer state] == NSDrawerOpeningState
69         forKey:MMShowLeftPlugInContainerKey];
72 - (void)initializeInstances
74     NSArray *plugInClasses = [[MMPlugInManager sharedManager] plugInClasses];
75     int i, count = [plugInClasses count];
76     for (i = 0; i < count; i++) {
77         Class plugInClass = [plugInClasses objectAtIndex:i];
78         if ([plugInClass instancesRespondToSelector:
79                          @selector(initWithMediator:)]) {
80             id instance = [[[plugInClass alloc] initWithMediator:self] autorelease];
81             [instances addObject:instance];
82         }
83     }
86 - (id)initWithVimController:(MMVimController *)controller
88     if ((self = [super init]) == nil) return nil;
89     vimController = controller;
90     instances = [[NSMutableArray alloc] init];
91     plugInViews = [[NSMutableArray alloc] init];
93     [self setupDrawer];
94     [self initializeInstances];
96     return self;
99 - (void)dealloc
101     ASLogDebug(@"");
103     [plugInViews release]; plugInViews = nil;
104     [instances release]; instances = nil;
105     [drawer release]; drawer = nil;
106     vimController = nil;
108     [super dealloc];
111 - (id)evaluateVimExpression:(NSString *)vimExpression
113     NSString *errstr = nil;
114     id res = [vimController evaluateVimExpressionCocoa:vimExpression
115                                            errorString:&errstr];
116     if (!res) {
117         // Setting format to %@ instead of just passing errstr avoids warning.
118         [NSException raise:@"VimEvaluationException" format:@"%@", errstr];
119     }
121     return res;
124 - (void)addVimInput:(NSString *)input
126     [vimController addVimInput:input];
129 - (void)addPlugInView:(NSView *)view withTitle:(NSString *)title
131     // Do this here so that the drawer is never opened automatically when there
132     // are no plugin views.
133     if ([[NSUserDefaults standardUserDefaults]
134             boolForKey:MMShowLeftPlugInContainerKey] && [plugInViews count] == 0)
135         [drawer open];
137     MMPlugInViewController *newView =
138         [[MMPlugInViewController alloc] initWithView:view title:title];
140     [plugInViews addObject:newView];
142     [newView moveToContainer:(MMPlugInViewContainer *)[drawer contentView]];
144     [newView release];
147 - (void)openFiles:(NSArray *)filenames
149     [vimController dropFiles:filenames forceOpen:YES];
152 - (id)instanceWithClass:(Class)class
154     int i, count = [instances count];
155     for (i = 0; i < count; i++) {
156         id instance = [instances objectAtIndex:i];
157         if ([instance isKindOfClass:class])
158             return instance;
159     }
161     return nil;
164 @end
166 @implementation MMPlugInAppMediator
168 MMPlugInAppMediator *sharedAppMediator = nil;
170 + (MMPlugInAppMediator *)sharedAppMediator
172     if (sharedAppMediator == nil)
173         sharedAppMediator = [[MMPlugInAppMediator alloc] init];
175     return sharedAppMediator;
178 - (id)init
180     if ((self = [super init]) == nil) return nil;
182     NSString *title = NSLocalizedString(@"Toggle Left Drawer",
183                                         @"Toggle Left Drawer menu title");
184     NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:title
185                                            action:@selector(toggleLeftDrawer:)
186                                     keyEquivalent:@""] autorelease];
187     [item setTarget:self];
188     [self addPlugInMenuItem:item];
189     [self addPlugInMenuItem:[NSMenuItem separatorItem]];
191     return self;
194 - (void)toggleLeftDrawer:(id)sender
196     MMVimController *c = [[MMAppController sharedInstance] keyVimController];
198     [[c instanceMediator] toggleDrawer];
201 - (BOOL)validateMenuItem:(NSMenuItem *)item
203     return [[MMAppController sharedInstance] keyVimController] != nil;
206 - (void)addPlugInMenuItem:(NSMenuItem *)menuItem
208     NSAssert(menuItem, @"menuItem cannot be nil");
209     [[MMAppController sharedInstance] addItemToPlugInMenu:menuItem];
212 // It is a little bit ugly having to pass the class in here.  An alternative
213 // would be to have a 1:1 relationship between app mediators and plugins, so
214 // that we'd know exactly which plugin class to look for.
215 - (id)keyPlugInInstanceWithClass:(Class)class
217     MMVimController *keyVimController = [[NSApp delegate] keyVimController];
219     if (keyVimController)
220         return [[keyVimController instanceMediator] instanceWithClass:class];
222     return nil;
225 - (int)majorVersion
227     return MMPlugInArchMajorVersion;
230 - (int)minorVersion
232     return MMPlugInArchMinorVersion;
235 @end
237 #endif