1/* 2 GormViewKnobs.m 3 4 Copyright (C) 1999 Free Software Foundation, Inc. 5 6 Author: Gerrit van Dyk <gerritvd@decimax.com> 7 Date: 1999 8 Modified and extended by: Richard Frith-Macdonald <richard@brainstorm.co.uk> 9 10 This file is part of the GNUstep Interface Modeller Application. 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Library General Public 14 License as published by the Free Software Foundation; either 15 version 3 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Library General Public License for more details. 21 22 You should have received a copy of the GNU Library General Public 23 License along with this library; see the file COPYING.LIB. 24 If not, write to the Free Software Foundation, 25 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26*/ 27 28#include "GormViewKnobs.h" 29#include <math.h> 30 31static NSInteger KNOB_WIDTH = 0.0; 32static NSInteger KNOB_HEIGHT = 0.0; 33 34#define MINSIZE 5.0 35 36static NSRect *blackRectList = NULL; 37static int blackRectSize = 0; 38static int blackRectCount = 0; 39static NSRect *fgcolorRectList= NULL; 40static int fgcolorRectSize = 0; 41static int fgcolorRectCount= 0; 42 43static void _fastKnobFill(NSRect aRect,BOOL isBlack); 44static void _drawKnobsForRect(NSRect aRect,BOOL isBlack); 45 46static void 47calcKnobSize(void) 48{ 49 NSString *value; 50 float w = 2.0; 51 float h = 2.0; 52 53 value = [[NSUserDefaults standardUserDefaults] objectForKey: @"KnobWidth"]; 54 if (value != nil) 55 { 56 w = floor([value floatValue] / 2.0); 57 } 58 value = [[NSUserDefaults standardUserDefaults] objectForKey: @"KnobHeight"]; 59 if (value != nil) 60 { 61 h = floor([value floatValue] / 2.0); 62 } 63 w = MAX(w, 1.0); 64 h = MAX(h, 1.0); 65 KNOB_WIDTH = w * 2.0 + 1.0; // Size must be odd */ 66 KNOB_HEIGHT = h * 2.0 + 1.0; 67} 68 69void 70GormShowFastKnobFills(void) 71{ 72 if (blackRectCount) 73 { 74 [[NSColor blackColor] set]; 75 NSRectFillList(blackRectList, blackRectCount); 76 } 77 if (fgcolorRectCount) 78 { 79 [[NSColor redColor] set]; 80 NSRectFillList(fgcolorRectList, fgcolorRectCount); 81 } 82 blackRectCount = 0; 83 fgcolorRectCount = 0; 84} 85 86static void 87_showLitKnobForRect(NSRect frame, IBKnobPosition aKnob) 88{ 89 float dx, dy; 90 BOOL oddx, oddy; 91 NSRect r; 92 93 if (!KNOB_WIDTH) 94 { 95 calcKnobSize(); 96 } 97 dx = NSWidth(frame) / 2.0; 98 dy = NSHeight(frame) / 2.0; 99 oddx = (floor(dx) != dx); 100 oddy = (floor(dy) != dy); 101 frame.size.width = KNOB_WIDTH; 102 frame.size.height = KNOB_HEIGHT; 103 frame.origin.x -= ((KNOB_WIDTH - 1.0) / 2.0); 104 frame.origin.y -= ((KNOB_HEIGHT - 1.0) / 2.0); 105 106 // Initialize r to keep the compiler happy 107 r = frame; 108 109 if (aKnob == IBBottomLeftKnobPosition) 110 r = frame; 111 frame.origin.y += dy; 112 if (oddy) 113 frame.origin.y -= 0.5; 114 if (aKnob == IBMiddleLeftKnobPosition) 115 r = frame; 116 frame.origin.y += dy; 117 if (oddy) 118 frame.origin.y += 0.5; 119 if (aKnob == IBTopLeftKnobPosition) 120 r = frame; 121 frame.origin.x += dx; 122 if (oddx) 123 frame.origin.x -= 0.5; 124 if (aKnob == IBTopMiddleKnobPosition) 125 r = frame; 126 frame.origin.x += dx; 127 if (oddx) 128 frame.origin.x += 0.5; 129 if (aKnob == IBTopRightKnobPosition) 130 r = frame; 131 frame.origin.y -= dy; 132 if (oddy) 133 frame.origin.y -= 0.5; 134 if (aKnob == IBMiddleRightKnobPosition) 135 r = frame; 136 frame.origin.y -= dy; 137 if (oddy) 138 frame.origin.y += 0.5; 139 if (aKnob == IBBottomRightKnobPosition) 140 r = frame; 141 frame.origin.x -= dx; 142 if (oddx) 143 frame.origin.x += 0.5; 144 if (aKnob == IBBottomMiddleKnobPosition) 145 r = frame; 146 147 r.origin.x += 1.0; 148 r.origin.y -= 1.0; 149 [[NSColor blackColor] set]; 150 [NSBezierPath fillRect: r]; 151 r.origin.x -= 1.0; 152 r.origin.y += 1.0; 153 [[NSColor whiteColor] set]; 154 [NSBezierPath fillRect: r]; 155} 156 157void 158GormShowFrameWithKnob(NSRect aRect, IBKnobPosition aKnob) 159{ 160 NSRect r = aRect; 161 162 /* 163 * We draw a wire-frame around the rectangle. 164 */ 165 r.origin.x -= 0.5; 166 r.origin.y -= 0.5; 167 r.size.width += 1.0; 168 r.size.height += 1.0; 169 [[NSColor blackColor] set]; 170 [NSBezierPath strokeRect: r]; 171 172 if (aKnob != IBNoneKnobPosition) 173 { 174 /* 175 * NB. we use the internal rectangle for calculating the knob position. 176 */ 177 _showLitKnobForRect(aRect, aKnob); 178 } 179} 180 181void 182GormDrawKnobsForRect(NSRect aRect) 183{ 184 NSRect r; 185 186 r.origin.x = floor(NSMinX(aRect)); 187 r.origin.y = floor(NSMinY(aRect)); 188 r.size.width = floor(NSMaxX(aRect) + 0.99) - NSMinX(r); 189 r.size.height = floor(NSMaxY(aRect) + 0.99) - NSMinY(r); 190 r.origin.x += 1.0; 191 r.origin.y -= 1.0; 192 _drawKnobsForRect(r, YES); 193 r.origin.x = floor(NSMinX(aRect)); 194 r.origin.y = floor(NSMinY(aRect)); 195 r.size.width = floor(NSMaxX(aRect) + 0.99) - NSMinX(r); 196 r.size.height = floor(NSMaxY(aRect) + 0.99) - NSMinY(r); 197 _drawKnobsForRect(r, NO); 198} 199 200/* Draw these around an NSBox whose contents are being edited. 201*/ 202void 203GormDrawOpenKnobsForRect(NSRect aRect) 204{ 205 NSRect r; 206 207 r.origin.x = floor(NSMinX(aRect)); 208 r.origin.y = floor(NSMinY(aRect)); 209 r.size.width = floor(NSMaxX(aRect) + 0.99) - NSMinX(r); 210 r.size.height = floor(NSMaxY(aRect) + 0.99) - NSMinY(r); 211 _drawKnobsForRect(r, YES); 212} 213 214IBKnobPosition 215GormKnobHitInRect(NSRect aFrame, NSPoint p) 216{ 217 NSRect eb; 218 NSRect knob; 219 float dx, dy; 220 BOOL oddx, oddy; 221 222 eb = GormExtBoundsForRect(aFrame); 223 224 if (!NSMouseInRect(p, eb, NO)) 225 { 226 return IBNoneKnobPosition; 227 } 228 knob = aFrame; 229 dx = NSWidth(knob) / 2.0; 230 dy = NSHeight(knob) / 2.0; 231 oddx = (floor(dx) != dx); 232 oddy = (floor(dy) != dy); 233 knob.size.width = KNOB_WIDTH; 234 knob.size.height = KNOB_HEIGHT; 235 knob.origin.x -= ((KNOB_WIDTH - 1.0) / 2.0); 236 knob.origin.y -= ((KNOB_HEIGHT - 1.0) / 2.0); 237 238 if (NSMouseInRect(p, knob, NO)) 239 { 240 return(IBBottomLeftKnobPosition); 241 } 242 knob.origin.y += dy; 243 if (oddy) 244 { 245 knob.origin.y -= 0.5; 246 } 247 if (NSMouseInRect(p, knob, NO)) 248 { 249 return(IBMiddleLeftKnobPosition); 250 } 251 knob.origin.y += dy; 252 if (oddy) 253 { 254 knob.origin.y += 0.5; 255 } 256 if (NSMouseInRect(p, knob, NO)) 257 { 258 return(IBTopLeftKnobPosition); 259 } 260 knob.origin.x += dx; 261 if (oddx) 262 { 263 knob.origin.x -= 0.5; 264 } 265 if (NSMouseInRect(p, knob, NO)) 266 { 267 return(IBTopMiddleKnobPosition); 268 } 269 knob.origin.x += dx; 270 if (oddx) 271 { 272 knob.origin.x += 0.5; 273 } 274 if (NSMouseInRect(p, knob, NO)) 275 { 276 return(IBTopRightKnobPosition); 277 } 278 knob.origin.y -= dy; 279 if (oddy) 280 { 281 knob.origin.y -= 0.5; 282 } 283 if (NSMouseInRect(p, knob, NO)) 284 { 285 return(IBMiddleRightKnobPosition); 286 } 287 knob.origin.y -= dy; 288 if (oddy) 289 { 290 knob.origin.y += 0.5; 291 } 292 if (NSMouseInRect(p, knob, NO)) 293 { 294 return(IBBottomRightKnobPosition); 295 } 296 knob.origin.x -= dx; 297 if (oddx) 298 { 299 knob.origin.x += 0.5; 300 } 301 if (NSMouseInRect(p, knob, NO)) 302 { 303 return(IBBottomMiddleKnobPosition); 304 } 305 306 return IBNoneKnobPosition; 307} 308 309NSRect 310GormExtBoundsForRect(NSRect aRect) 311{ 312 NSRect returnRect; 313 314 if (NSWidth(aRect) < 0.0) 315 { 316 returnRect.origin.x = NSMaxX(aRect); 317 returnRect.size.width = - NSWidth(aRect); 318 } 319 else 320 { 321 returnRect.origin.x = NSMinX(aRect); 322 returnRect.size.width = NSWidth(aRect); 323 } 324 if (aRect.size.height < 0.0) 325 { 326 returnRect.origin.y = NSMaxY(aRect); 327 returnRect.size.height = - NSHeight(aRect); 328 } 329 else 330 { 331 returnRect.origin.y = NSMinY(aRect); 332 returnRect.size.height = NSHeight(aRect); 333 } 334 335 returnRect.size.width = MAX(1.0, NSWidth(returnRect)); 336 returnRect.size.height = MAX(1.0, NSHeight(returnRect)); 337 338 returnRect = NSInsetRect(returnRect, 339 - ((KNOB_WIDTH - 1.0) + 1.0), - ((KNOB_HEIGHT - 1.0) + 1.0)); 340 341 return NSIntegralRect(returnRect); 342} 343 344static void 345_fastKnobFill(NSRect aRect, BOOL isBlack) 346{ 347 if (isBlack) 348 { 349 if (!blackRectList) 350 { 351 blackRectSize = 16; 352 blackRectList = NSZoneMalloc(NSDefaultMallocZone(), 353 blackRectSize * sizeof(NSRect)); 354 } 355 else 356 { 357 if (blackRectCount >= blackRectSize) 358 { 359 while (blackRectCount >= blackRectSize) 360 { 361 blackRectSize <<= 1; 362 } 363 blackRectList = NSZoneRealloc(NSDefaultMallocZone(), blackRectList, 364 blackRectSize * sizeof(NSRect)); 365 } 366 } 367 blackRectList[blackRectCount++] = aRect; 368 } 369 else 370 { 371 if (!fgcolorRectList) 372 { 373 fgcolorRectSize = 16; 374 fgcolorRectList = NSZoneMalloc(NSDefaultMallocZone(), 375 fgcolorRectSize * sizeof(NSRect)); 376 } 377 else 378 { 379 if (fgcolorRectCount >= fgcolorRectSize) 380 { 381 while (fgcolorRectCount >= fgcolorRectSize) 382 { 383 fgcolorRectSize <<= 1; 384 } 385 fgcolorRectList = NSZoneRealloc(NSDefaultMallocZone(), fgcolorRectList, 386 fgcolorRectSize * sizeof(NSRect)); 387 } 388 } 389 fgcolorRectList[fgcolorRectCount++] = aRect; 390 } 391} 392 393static void 394_drawKnobsForRect(NSRect knob, BOOL isBlack) 395{ 396 float dx, dy; 397 BOOL oddx, oddy; 398 399 if (!KNOB_WIDTH) 400 { 401 calcKnobSize(); 402 } 403 dx = NSWidth(knob) / 2.0; 404 dy = NSHeight(knob) / 2.0; 405 oddx = (floor(dx) != dx); 406 oddy = (floor(dy) != dy); 407 knob.size.width = KNOB_WIDTH; 408 knob.size.height = KNOB_HEIGHT; 409 knob.origin.x -= ((KNOB_WIDTH - 1.0) / 2.0); 410 knob.origin.y -= ((KNOB_HEIGHT - 1.0) / 2.0); 411 412 _fastKnobFill(knob, isBlack); 413 knob.origin.y += dy; 414 if (oddy) 415 { 416 knob.origin.y -= 0.5; 417 } 418 _fastKnobFill(knob, isBlack); 419 knob.origin.y += dy; 420 if (oddy) 421 { 422 knob.origin.y += 0.5; 423 } 424 _fastKnobFill(knob, isBlack); 425 knob.origin.x += dx; 426 if (oddx) 427 { 428 knob.origin.x -= 0.5; 429 } 430 _fastKnobFill(knob, isBlack); 431 knob.origin.x += dx; 432 if (oddx) 433 { 434 knob.origin.x += 0.5; 435 } 436 _fastKnobFill(knob, isBlack); 437 knob.origin.y -= dy; 438 if (oddy) 439 { 440 knob.origin.y -= 0.5; 441 } 442 _fastKnobFill(knob, isBlack); 443 knob.origin.y -= dy; 444 if (oddy) 445 { 446 knob.origin.y += 0.5; 447 } 448 _fastKnobFill(knob, isBlack); 449 knob.origin.x -= dx; 450 if (oddx) 451 { 452 knob.origin.x += 0.5; 453 } 454 _fastKnobFill(knob, isBlack); 455} 456 457