trunk/src/osd/modules/debugger/osx/debugview.m
| r243705 | r243706 | |
| 165 | 165 | |
| 166 | 166 | |
| 167 | 167 | - (void)recomputeVisible { |
| 168 | | if ([self window] != nil) |
| 169 | | { |
| 170 | | // this gets all the lines that are at least partially visible |
| 171 | | debug_view_xy origin(0, 0), size(totalWidth, totalHeight); |
| 172 | | [self convertBounds:[self visibleRect] toFirstAffectedLine:&origin.y count:&size.y]; |
| 168 | // this gets all the lines that are at least partially visible |
| 169 | debug_view_xy origin(0, 0), size(totalWidth, totalHeight); |
| 170 | [self convertBounds:[self visibleRect] toFirstAffectedLine:&origin.y count:&size.y]; |
| 173 | 171 | |
| 174 | | // tell them what we think |
| 175 | | view->set_visible_size(size); |
| 176 | | view->set_visible_position(origin); |
| 177 | | originLeft = origin.x; |
| 178 | | originTop = origin.y; |
| 179 | | } |
| 172 | // tell the underlying view how much real estate is available |
| 173 | view->set_visible_size(size); |
| 174 | view->set_visible_position(origin); |
| 175 | originTop = origin.y; |
| 180 | 176 | } |
| 181 | 177 | |
| 182 | 178 | |
| 183 | 179 | - (void)typeCharacterAndScrollToCursor:(char)ch { |
| 184 | | if (view->cursor_supported()) |
| 180 | debug_view_xy const oldPos = view->cursor_position(); |
| 181 | view->process_char(ch); |
| 182 | if (view->cursor_supported() && view->cursor_visible()) |
| 185 | 183 | { |
| 186 | | debug_view_xy const oldPos = view->cursor_position(); |
| 187 | | view->process_char(ch); |
| 188 | 184 | debug_view_xy const newPos = view->cursor_position(); |
| 189 | 185 | if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) |
| 190 | 186 | { |
| r243705 | r243706 | |
| 194 | 190 | fontWidth, |
| 195 | 191 | fontHeight)]; |
| 196 | 192 | } |
| 197 | | } else { |
| 198 | | view->process_char(ch); |
| 199 | 193 | } |
| 200 | 194 | } |
| 201 | 195 | |
| r243705 | r243706 | |
| 216 | 210 | return nil; |
| 217 | 211 | } |
| 218 | 212 | totalWidth = totalHeight = 0; |
| 219 | | originLeft = originTop = 0; |
| 213 | originTop = 0; |
| 220 | 214 | |
| 221 | 215 | text = [[NSTextStorage alloc] init]; |
| 222 | 216 | textContainer = [[NSTextContainer alloc] init]; |
| r243705 | r243706 | |
| 261 | 255 | debug_view_xy const newOrigin = view->visible_position(); |
| 262 | 256 | if (newOrigin.y != originTop) |
| 263 | 257 | { |
| 264 | | [self scrollPoint:NSMakePoint([self visibleRect].origin.x, newOrigin.y * fontHeight)]; |
| 258 | NSRect const visible = [self visibleRect]; |
| 259 | NSPoint scroll = NSMakePoint(visible.origin.x, newOrigin.y * fontHeight); |
| 260 | if ((newOrigin.y + view->visible_size().y) == totalHeight) |
| 261 | scroll.y += (view->visible_size().y * fontHeight) - visible.size.height; |
| 262 | [self scrollPoint:scroll]; |
| 265 | 263 | originTop = newOrigin.y; |
| 266 | 264 | } |
| 267 | 265 | |
| 268 | | // recompute the visible area and mark as dirty |
| 269 | | [self recomputeVisible]; |
| 266 | // mark as dirty |
| 270 | 267 | [self setNeedsDisplay:YES]; |
| 271 | 268 | } |
| 272 | 269 | |
| r243705 | r243706 | |
| 389 | 386 | NSData *const data = [[board stringForType:avail] dataUsingEncoding:NSASCIIStringEncoding |
| 390 | 387 | allowLossyConversion:YES]; |
| 391 | 388 | char const *const bytes = (char const *)[data bytes]; |
| 389 | debug_view_xy const oldPos = view->cursor_position(); |
| 392 | 390 | for (NSUInteger i = 0, l = [data length]; i < l; i++) |
| 393 | 391 | view->process_char(bytes[i]); |
| 392 | if (view->cursor_supported() && view->cursor_visible()) |
| 393 | { |
| 394 | debug_view_xy const newPos = view->cursor_position(); |
| 395 | if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) |
| 396 | { |
| 397 | // FIXME - use proper font metrics |
| 398 | [self scrollRectToVisible:NSMakeRect((newPos.x * fontWidth) + [textContainer lineFragmentPadding], |
| 399 | newPos.y * fontHeight, |
| 400 | fontWidth, |
| 401 | fontHeight)]; |
| 402 | } |
| 403 | } |
| 394 | 404 | } |
| 395 | 405 | |
| 396 | 406 | |
| 407 | - (void)viewBoundsDidChange:(NSNotification *)notification { |
| 408 | NSView *const changed = [notification object]; |
| 409 | if (changed == [[self enclosingScrollView] contentView]) |
| 410 | [self recomputeVisible]; |
| 411 | } |
| 412 | |
| 413 | |
| 397 | 414 | - (void)windowDidBecomeKey:(NSNotification *)notification { |
| 398 | | NSWindow *win = [notification object]; |
| 415 | NSWindow *const win = [notification object]; |
| 399 | 416 | if ((win == [self window]) && ([win firstResponder] == self) && view->cursor_supported()) |
| 400 | 417 | [self setNeedsDisplay:YES]; |
| 401 | 418 | } |
| 402 | 419 | |
| 403 | 420 | |
| 404 | 421 | - (void)windowDidResignKey:(NSNotification *)notification { |
| 405 | | NSWindow *win = [notification object]; |
| 422 | NSWindow *const win = [notification object]; |
| 406 | 423 | if ((win == [self window]) && ([win firstResponder] == self) && view->cursor_supported()) |
| 407 | 424 | [self setNeedsDisplay:YES]; |
| 408 | 425 | } |
| r243705 | r243706 | |
| 429 | 446 | |
| 430 | 447 | |
| 431 | 448 | - (BOOL)becomeFirstResponder { |
| 432 | | if (view->cursor_supported()) { |
| 449 | if (view->cursor_supported()) |
| 450 | { |
| 433 | 451 | debug_view_xy pos; |
| 434 | 452 | view->set_cursor_visible(true); |
| 435 | 453 | pos = view->cursor_position(); |
| 436 | 454 | [self scrollRectToVisible:NSMakeRect((pos.x * fontWidth) + [textContainer lineFragmentPadding], pos.y * fontHeight, fontWidth, fontHeight)]; // FIXME: metrics |
| 437 | 455 | [self setNeedsDisplay:YES]; |
| 438 | 456 | return [super becomeFirstResponder]; |
| 439 | | } else { |
| 457 | } |
| 458 | else |
| 459 | { |
| 440 | 460 | return NO; |
| 441 | 461 | } |
| 442 | 462 | } |
| r243705 | r243706 | |
| 450 | 470 | |
| 451 | 471 | |
| 452 | 472 | - (void)viewDidMoveToSuperview { |
| 453 | | [[self enclosingScrollView] setLineScroll:fontHeight]; |
| 454 | 473 | [super viewDidMoveToSuperview]; |
| 474 | |
| 475 | [[NSNotificationCenter defaultCenter] removeObserver:self |
| 476 | name:NSViewBoundsDidChangeNotification |
| 477 | object:nil]; |
| 478 | |
| 479 | NSScrollView *const scroller = [self enclosingScrollView]; |
| 480 | if (scroller != nil) |
| 481 | { |
| 482 | [scroller setLineScroll:fontHeight]; |
| 483 | [[scroller contentView] setPostsBoundsChangedNotifications:YES]; |
| 484 | [[NSNotificationCenter defaultCenter] addObserver:self |
| 485 | selector:@selector(viewBoundsDidChange:) |
| 486 | name:NSViewBoundsDidChangeNotification |
| 487 | object:[scroller contentView]]; |
| 488 | } |
| 455 | 489 | } |
| 456 | 490 | |
| 457 | 491 | |
| 458 | 492 | - (void)viewDidMoveToWindow { |
| 459 | | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil]; |
| 460 | | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:nil]; |
| 461 | | if ([self window] != nil) { |
| 493 | [super viewDidMoveToWindow]; |
| 494 | |
| 495 | [[NSNotificationCenter defaultCenter] removeObserver:self |
| 496 | name:NSWindowDidBecomeKeyNotification |
| 497 | object:nil]; |
| 498 | [[NSNotificationCenter defaultCenter] removeObserver:self |
| 499 | name:NSWindowDidResignKeyNotification |
| 500 | object:nil]; |
| 501 | |
| 502 | if ([self window] != nil) |
| 503 | { |
| 462 | 504 | [[NSNotificationCenter defaultCenter] addObserver:self |
| 463 | 505 | selector:@selector(windowDidBecomeKey:) |
| 464 | 506 | name:NSWindowDidBecomeKeyNotification |
| r243705 | r243706 | |
| 467 | 509 | selector:@selector(windowDidResignKey:) |
| 468 | 510 | name:NSWindowDidResignKeyNotification |
| 469 | 511 | object:[self window]]; |
| 470 | | [self recomputeVisible]; |
| 512 | [self setNeedsDisplay:YES]; |
| 471 | 513 | } |
| 472 | 514 | } |
| 473 | 515 | |
| r243705 | r243706 | |
| 483 | 525 | |
| 484 | 526 | |
| 485 | 527 | - (void)drawRect:(NSRect)dirtyRect { |
| 486 | | INT32 position, clip; |
| 487 | | |
| 488 | | // work out how much we need to draw |
| 528 | // work out what's available |
| 489 | 529 | [self recomputeVisible]; |
| 490 | 530 | debug_view_xy const origin = view->visible_position(); |
| 491 | 531 | debug_view_xy const size = view->visible_size(); |
| 532 | |
| 533 | // work out how much we need to draw |
| 534 | INT32 position, clip; |
| 492 | 535 | [self convertBounds:dirtyRect toFirstAffectedLine:&position count:&clip]; |
| 493 | 536 | |
| 494 | 537 | // this gets the text for the whole visible area |
| r243705 | r243706 | |
| 500 | 543 | for (UINT32 row = position; row < position + clip; row++, data += size.x) |
| 501 | 544 | { |
| 502 | 545 | if ((row < origin.y) || (row >= origin.y + size.y)) |
| 546 | { |
| 547 | [DefaultBackground set]; |
| 548 | [NSBezierPath fillRect:NSMakeRect(0, |
| 549 | row * fontHeight, |
| 550 | [self bounds].size.width, |
| 551 | fontHeight)]; |
| 503 | 552 | continue; |
| 553 | } |
| 504 | 554 | |
| 505 | 555 | // render entire lines to get character alignment right |
| 506 | 556 | int attr = -1; |