1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. 5 * 6 * The contents of this file are subject to the terms of either the GNU Lesser 7 * General Public License Version 2.1 only ("LGPL") or the Common Development and 8 * Distribution License ("CDDL")(collectively, the "License"). You may not use this 9 * file except in compliance with the License. You can obtain a copy of the CDDL at 10 * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at 11 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the 12 * specific language governing permissions and limitations under the License. When 13 * distributing the software, include this License Header Notice in each file and 14 * include the full text of the License in the License file as well as the 15 * following notice: 16 * 17 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 18 * (CDDL) 19 * For Covered Software in this distribution, this License shall be governed by the 20 * laws of the State of California (excluding conflict-of-law provisions). 21 * Any litigation relating to this License shall be subject to the jurisdiction of 22 * the Federal Courts of the Northern District of California and the state courts 23 * of the State of California, with venue lying in Santa Clara County, California. 24 * 25 * Contributor(s): 26 * 27 * If you wish your version of this file to be governed by only the CDDL or only 28 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to 29 * include this software in this distribution under the [CDDL or LGPL Version 2.1] 30 * license." If you don't indicate a single choice of license, a recipient has the 31 * option to distribute your version of this file under either the CDDL or the LGPL 32 * Version 2.1, or to extend the choice of license to its licensees as provided 33 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL 34 * Version 2 license, then the option applies only if the new code is made subject 35 * to such option by the copyright holder. 36 */ 37 38 #import "Carbon/Carbon.h" 39 #import "CandidateWindow.h" 40 41 static void tuningFrameForScreen (NSRect *, NSSize, NSRect); 42 43 @interface CandidateView : NSView { 44 NSAttributedString *_string; 45 } 46 47 -(void) setAttributedString:(NSAttributedString *)str; 48 49 @end 50 51 @implementation CandidateView 52 53 -(void) setAttributedString:(NSAttributedString *)str 54 { 55 [str retain]; 56 [_string release]; 57 _string = str; 58 [self setNeedsDisplay:YES]; 59 } 60 61 - (void)drawRect:(NSRect)rect 62 { 63 if (!_string) 64 return; 65 66 NSPoint stringOrigin; 67 NSSize stringSize = [_string size]; 68 stringOrigin.x = rect.origin.x + ( rect.size.width - stringSize.width)/2; 69 stringOrigin.y = rect.origin.y + ( rect.size.height - stringSize.height)/2; 70 [_string drawAtPoint:stringOrigin]; 71 } 72 73 - (void) dealloc 74 { 75 [_string release]; 76 [super dealloc]; 77 } 78 79 @end 80 81 @implementation CandidateWindow 82 83 -(id)init 84 { 85 _font = [[NSFont fontWithName:@"Hei" size:16] retain]; 86 _bgColor = [[NSColor colorWithDeviceRed:1.0 green:0.5 blue:0.0 alpha:0.8] retain]; 87 _fgColor = [[NSColor whiteColor] retain]; 88 _hlColor = [[NSColor blueColor] retain]; 89 90 _attr = [[NSMutableDictionary alloc] init]; 91 [_attr setObject:_fgColor forKey:NSForegroundColorAttributeName]; 92 [_attr setObject:_font forKey:NSFontAttributeName]; 93 94 _window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,0,0) 95 styleMask:NSBorderlessWindowMask 96 backing:NSBackingStoreBuffered 97 defer:NO]; 98 99 [_window setLevel:NSScreenSaverWindowLevel]; 100 [_window setHasShadow: YES]; 101 [_window setOpaque:NO]; 102 103 [_window setBackgroundColor:_bgColor]; 104 105 _view = [[CandidateView alloc] initWithFrame:[[_window contentView] frame]]; 106 [_window setContentView:_view]; 107 108 return self; 109 } 110 111 -(NSFont *)font 112 { 113 return _font; 114 } 115 116 -(void)setFont:(NSFont*)font 117 { 118 [font retain]; 119 [_font release]; 120 _font = font; 121 [_attr setObject:_font forKey:NSFontAttributeName]; 122 } 123 124 -(NSColor *)bgColor 125 { 126 return _bgColor; 127 } 128 129 -(void)setBgColor:(NSColor*)color 130 { 131 [color retain]; 132 [_bgColor release]; 133 _bgColor = color; 134 [_window setBackgroundColor:color]; 135 } 136 137 -(NSColor *)fgColor 138 { 139 return _fgColor; 140 } 141 142 -(void)setFgColor:(NSColor*)color 143 { 144 [color retain]; 145 [_fgColor release]; 146 _fgColor = color; 147 } 148 149 -(NSColor *)hlColor 150 { 151 return _hlColor; 152 } 153 154 -(void)setHlColor:(NSColor*)color 155 { 156 [color retain]; 157 [_hlColor release]; 158 _hlColor = color; 159 } 160 161 -(void)showCandidates:(NSArray *)candiArray around:(NSRect)cursorRect 162 { 163 if ([candiArray count] == 0) { 164 [self hideCandidates]; 165 return; 166 } 167 168 [_attr setObject:_fgColor forKey:NSForegroundColorAttributeName]; 169 [_attr setObject:_font forKey:NSFontAttributeName]; 170 171 int i; 172 NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init]; 173 for (i=0; i<[candiArray count]; i++) { 174 NSString *str = [NSString stringWithFormat:@"%d.%@ ", i+1, [candiArray objectAtIndex:i]]; 175 NSAttributedString *astr = [[[NSAttributedString alloc] initWithString:str attributes:_attr] autorelease]; 176 [string appendAttributedString:astr]; 177 178 if (i==0) 179 [string addAttribute:NSForegroundColorAttributeName 180 value:_hlColor 181 range:NSMakeRange(0, [str length])]; 182 } 183 184 NSRect winRect = [_window frame]; 185 NSSize strSize = [string size]; 186 187 tuningFrameForScreen (&winRect, strSize, cursorRect); 188 [_window setFrame:winRect display:NO]; 189 190 [(CandidateView*)_view setAttributedString:string]; 191 [string release]; 192 193 [_window orderFront:nil]; 194 } 195 196 -(void)hideCandidates 197 { 198 [_window orderOut:self]; 199 } 200 201 - (void) dealloc 202 { 203 [_font release]; 204 [_bgColor release]; 205 [_fgColor release]; 206 [_hlColor release]; 207 [_attr release]; 208 [_view release]; 209 [_window release]; 210 [super dealloc]; 211 } 212 213 @end 214 215 static void tuningFrameForScreen (NSRect *winRect, NSSize strSize, NSRect cursorRect) 216 { 217 /* caculate the initial window's size */ 218 winRect->size.height = strSize.height+5; 219 winRect->size.width = strSize.width+5; 220 winRect->origin.x = cursorRect.origin.x + 2; 221 winRect->origin.y = cursorRect.origin.y - winRect->size.height -2; 222 223 /* find a proper screen by input cursor */ 224 NSRect screenRect = [[NSScreen mainScreen] frame]; 225 NSArray *screens =[NSScreen screens]; 226 int i, num_of_scrs = [screens count]; 227 228 /* no choices, just use mainScreen */ 229 if (num_of_scrs == 1) 230 goto FOUND_SCREEN; 231 232 for (i=0; i<num_of_scrs; i++) { 233 NSScreen *screen = [screens objectAtIndex:i]; 234 NSRect rect = [screen frame]; 235 if (NSPointInRect (cursorRect.origin, rect)) { 236 screenRect = rect; 237 goto FOUND_SCREEN; 238 } 239 } 240 241 /* find a proper screen by mouse position */ 242 HIPoint p; 243 HIGetMousePosition (kHICoordSpaceScreenPixel, NULL, &p); 244 NSPoint mousePosition; 245 mousePosition.x = p.x; 246 mousePosition.y = screenRect.size.height - p.y; 247 248 for (i=0; i<num_of_scrs; i++) { 249 NSScreen *screen = [screens objectAtIndex:i]; 250 NSRect rect = [screen frame]; 251 if (NSPointInRect (mousePosition, rect)) { 252 screenRect = rect; 253 goto FOUND_SCREEN; 254 } 255 } 256 257 FOUND_SCREEN:; 258 CGFloat min_x = NSMinX (screenRect), max_x = NSMaxX (screenRect); 259 CGFloat min_y = NSMinY (screenRect); 260 261 if (winRect->origin.x > max_x - winRect->size.width) 262 winRect->origin.x = max_x - winRect->size.width; 263 264 if (winRect->origin.x < min_x) 265 winRect->origin.x = min_x; 266 267 if (winRect->origin.y < min_y) 268 winRect->origin.y = cursorRect.origin.y > min_y? 269 cursorRect.origin.y + cursorRect.size.height + 2: 270 min_y; 271 } 272