diff options
Diffstat (limited to 'cocoa/InfoBar.mm')
| -rw-r--r-- | cocoa/InfoBar.mm | 530 |
1 files changed, 244 insertions, 286 deletions
diff --git a/cocoa/InfoBar.mm b/cocoa/InfoBar.mm index 7f86ad697..eb37124a8 100644 --- a/cocoa/InfoBar.mm +++ b/cocoa/InfoBar.mm @@ -18,23 +18,20 @@ // Inspired by code from Daniel Jalkut, Red Sweater Software. -- (NSRect) drawingRectForBounds: (NSRect) theRect -{ +- (NSRect) drawingRectForBounds: (NSRect) theRect { // Get the parent's idea of where we should draw NSRect newRect = [super drawingRectForBounds: theRect]; // When the text field is being edited or selected, we have to turn off the magic because it - // screws up the configuration of the field editor. We sneak around this by intercepting - // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute. - if (mIsEditingOrSelecting == NO) - { + // screws up the configuration of the field editor. We sneak around this by intercepting + // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute. + if (mIsEditingOrSelecting == NO) { // Get our ideal size for current text NSSize textSize = [self cellSizeForBounds: theRect]; // Center that in the proposed rect CGFloat heightDelta = newRect.size.height - textSize.height; - if (heightDelta > 0) - { + if (heightDelta > 0) { newRect.size.height -= heightDelta; newRect.origin.y += ceil(heightDelta / 2); } @@ -45,32 +42,30 @@ //-------------------------------------------------------------------------------------------------- -- (void) selectWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj - delegate:(id) anObject start: (NSInteger) selStart length: (NSInteger) selLength -{ +- (void) selectWithFrame: (NSRect) aRect inView: (NSView *) controlView editor: (NSText *) textObj + delegate: (id) anObject start: (NSInteger) selStart length: (NSInteger) selLength { aRect = [self drawingRectForBounds: aRect]; mIsEditingOrSelecting = YES; [super selectWithFrame: aRect - inView: controlView - editor: textObj - delegate: anObject - start: selStart - length: selLength]; + inView: controlView + editor: textObj + delegate: anObject + start: selStart + length: selLength]; mIsEditingOrSelecting = NO; } //-------------------------------------------------------------------------------------------------- -- (void) editWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj - delegate: (id) anObject event: (NSEvent*) theEvent -{ +- (void) editWithFrame: (NSRect) aRect inView: (NSView *) controlView editor: (NSText *) textObj + delegate: (id) anObject event: (NSEvent *) theEvent { aRect = [self drawingRectForBounds: aRect]; mIsEditingOrSelecting = YES; [super editWithFrame: aRect - inView: controlView - editor: textObj - delegate: anObject - event: theEvent]; + inView: controlView + editor: textObj + delegate: anObject + event: theEvent]; mIsEditingOrSelecting = NO; } @@ -80,24 +75,22 @@ @implementation InfoBar -- (instancetype) initWithFrame: (NSRect) frame -{ - self = [super initWithFrame: frame]; - if (self) - { - NSBundle* bundle = [NSBundle bundleForClass: [InfoBar class]]; - - NSString* path = [bundle pathForResource: @"info_bar_bg" ofType: @"tiff" inDirectory: nil]; - mBackground = [[NSImage alloc] initWithContentsOfFile: path]; - if (!mBackground.valid) - NSLog(@"Background image for info bar is invalid."); - - mScaleFactor = 1.0; - mCurrentCaretX = 0; - mCurrentCaretY = 0; - [self createItems]; - } - return self; +- (instancetype) initWithFrame: (NSRect) frame { + self = [super initWithFrame: frame]; + if (self) { + NSBundle *bundle = [NSBundle bundleForClass: [InfoBar class]]; + + NSString *path = [bundle pathForResource: @"info_bar_bg" ofType: @"tiff" inDirectory: nil]; + mBackground = [[NSImage alloc] initWithContentsOfFile: path]; + if (!mBackground.valid) + NSLog(@"Background image for info bar is invalid."); + + mScaleFactor = 1.0; + mCurrentCaretX = 0; + mCurrentCaretY = 0; + [self createItems]; + } + return self; } //-------------------------------------------------------------------------------------------------- @@ -110,21 +103,19 @@ * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type. * @param value Carries the new zoom value if the type is a zoom change. */ -- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location - value: (float) value -{ - switch (type) - { - case IBNZoomChanged: - [self setScaleFactor: value adjustPopup: YES]; - break; - case IBNCaretChanged: - [self setCaretPosition: location]; - break; - case IBNStatusChanged: - mStatusTextLabel.stringValue = message; - break; - } +- (void) notify: (NotificationType) type message: (NSString *) message location: (NSPoint) location + value: (float) value { + switch (type) { + case IBNZoomChanged: + [self setScaleFactor: value adjustPopup: YES]; + break; + case IBNCaretChanged: + [self setCaretPosition: location]; + break; + case IBNStatusChanged: + mStatusTextLabel.stringValue = message; + break; + } } //-------------------------------------------------------------------------------------------------- @@ -132,94 +123,91 @@ /** * Used to set a protocol object we can use to send change notifications to. */ -- (void) setCallback: (id <InfoBarCommunicator>) callback -{ - mCallback = callback; +- (void) setCallback: (id <InfoBarCommunicator>) callback { + mCallback = callback; } //-------------------------------------------------------------------------------------------------- static NSString *DefaultScaleMenuLabels[] = { - @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%" + @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%" }; static float DefaultScaleMenuFactors[] = { - 0.2f, 0.3f, 0.5f, 0.75f, 1.0f, 1.3f, 1.6f, 2.0f, 2.5f, 3.0f + 0.2f, 0.3f, 0.5f, 0.75f, 1.0f, 1.3f, 1.6f, 2.0f, 2.5f, 3.0f }; static unsigned DefaultScaleMenuSelectedItemIndex = 4; static float BarFontSize = 10.0; -- (void) createItems -{ - // 1) The zoom popup. - unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *); - - // Create the popup button. - mZoomPopup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO]; - - // No border or background please. - [mZoomPopup.cell setBordered: NO]; - [mZoomPopup.cell setArrowPosition: NSPopUpArrowAtBottom]; - - // Fill it. - for (unsigned count = 0; count < numberOfDefaultItems; count++) - { - [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)]; - id currentItem = [mZoomPopup itemAtIndex: count]; - if (DefaultScaleMenuFactors[count] != 0.0) - [currentItem setRepresentedObject: @(DefaultScaleMenuFactors[count])]; - } - [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex]; - - // Hook it up. - mZoomPopup.target = self; - mZoomPopup.action = @selector(zoomItemAction:); - - // Set a suitable font. - mZoomPopup.font = [NSFont menuBarFontOfSize: BarFontSize]; - - // Make sure the popup is big enough to fit the cells. - [mZoomPopup sizeToFit]; - - // Don't let it become first responder - [mZoomPopup setRefusesFirstResponder: YES]; - - // put it in the scrollview. - [self addSubview: mZoomPopup]; - - // 2) The caret position label. - Class oldCellClass = [NSTextField cellClass]; - [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]]; - - mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)]; - [mCaretPositionLabel setBezeled: NO]; - [mCaretPositionLabel setBordered: NO]; - [mCaretPositionLabel setEditable: NO]; - [mCaretPositionLabel setSelectable: NO]; - [mCaretPositionLabel setDrawsBackground: NO]; - mCaretPositionLabel.font = [NSFont menuBarFontOfSize: BarFontSize]; - - NSTextFieldCell* cell = mCaretPositionLabel.cell; - cell.placeholderString = @"0:0"; - cell.alignment = NSCenterTextAlignment; - - [self addSubview: mCaretPositionLabel]; - - // 3) The status text. - mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)]; - [mStatusTextLabel setBezeled: NO]; - [mStatusTextLabel setBordered: NO]; - [mStatusTextLabel setEditable: NO]; - [mStatusTextLabel setSelectable: NO]; - [mStatusTextLabel setDrawsBackground: NO]; - mStatusTextLabel.font = [NSFont menuBarFontOfSize: BarFontSize]; - - cell = mStatusTextLabel.cell; - cell.placeholderString = @""; - - [self addSubview: mStatusTextLabel]; - - // Restore original cell class so that everything else doesn't get broken - [NSTextField setCellClass: oldCellClass]; +- (void) createItems { + // 1) The zoom popup. + unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *); + + // Create the popup button. + mZoomPopup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO]; + + // No border or background please. + [mZoomPopup.cell setBordered: NO]; + [mZoomPopup.cell setArrowPosition: NSPopUpArrowAtBottom]; + + // Fill it. + for (unsigned count = 0; count < numberOfDefaultItems; count++) { + [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)]; + id currentItem = [mZoomPopup itemAtIndex: count]; + if (DefaultScaleMenuFactors[count] != 0.0) + [currentItem setRepresentedObject: @(DefaultScaleMenuFactors[count])]; + } + [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex]; + + // Hook it up. + mZoomPopup.target = self; + mZoomPopup.action = @selector(zoomItemAction:); + + // Set a suitable font. + mZoomPopup.font = [NSFont menuBarFontOfSize: BarFontSize]; + + // Make sure the popup is big enough to fit the cells. + [mZoomPopup sizeToFit]; + + // Don't let it become first responder + [mZoomPopup setRefusesFirstResponder: YES]; + + // put it in the scrollview. + [self addSubview: mZoomPopup]; + + // 2) The caret position label. + Class oldCellClass = [NSTextField cellClass]; + [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]]; + + mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)]; + [mCaretPositionLabel setBezeled: NO]; + [mCaretPositionLabel setBordered: NO]; + [mCaretPositionLabel setEditable: NO]; + [mCaretPositionLabel setSelectable: NO]; + [mCaretPositionLabel setDrawsBackground: NO]; + mCaretPositionLabel.font = [NSFont menuBarFontOfSize: BarFontSize]; + + NSTextFieldCell *cell = mCaretPositionLabel.cell; + cell.placeholderString = @"0:0"; + cell.alignment = NSCenterTextAlignment; + + [self addSubview: mCaretPositionLabel]; + + // 3) The status text. + mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)]; + [mStatusTextLabel setBezeled: NO]; + [mStatusTextLabel setBordered: NO]; + [mStatusTextLabel setEditable: NO]; + [mStatusTextLabel setSelectable: NO]; + [mStatusTextLabel setDrawsBackground: NO]; + mStatusTextLabel.font = [NSFont menuBarFontOfSize: BarFontSize]; + + cell = mStatusTextLabel.cell; + cell.placeholderString = @""; + + [self addSubview: mStatusTextLabel]; + + // Restore original cell class so that everything else doesn't get broken + [NSTextField setCellClass: oldCellClass]; } //-------------------------------------------------------------------------------------------------- @@ -230,52 +218,45 @@ static float BarFontSize = 10.0; /** * Fill the background. */ -- (void) drawRect: (NSRect) rect -{ - // Since the background is seamless, we don't need to take care for the proper offset. - // Simply tile the background over the invalid rectangle. - NSPoint target = {rect.origin.x, 0}; - while (target.x < rect.origin.x + rect.size.width) - { - [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1]; - target.x += mBackground.size.width; - } - - // Draw separator lines between items. - NSRect verticalLineRect; - CGFloat component = 190.0 / 255.0; - NSColor* lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1]; - - if (mDisplayMask & IBShowZoom) - { - verticalLineRect = mZoomPopup.frame; - verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; - verticalLineRect.size.width = 1.0; - if (NSIntersectsRect(rect, verticalLineRect)) - { - [lineColor set]; - NSRectFill(verticalLineRect); - } - } - - if (mDisplayMask & IBShowCaretPosition) - { - verticalLineRect = mCaretPositionLabel.frame; - verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; - verticalLineRect.size.width = 1.0; - if (NSIntersectsRect(rect, verticalLineRect)) - { - [lineColor set]; - NSRectFill(verticalLineRect); - } - } +- (void) drawRect: (NSRect) rect { + // Since the background is seamless, we don't need to take care for the proper offset. + // Simply tile the background over the invalid rectangle. + NSPoint target = {rect.origin.x, 0}; + while (target.x < rect.origin.x + rect.size.width) { + [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1]; + target.x += mBackground.size.width; + } + + // Draw separator lines between items. + NSRect verticalLineRect; + CGFloat component = 190.0 / 255.0; + NSColor *lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1]; + + if (mDisplayMask & IBShowZoom) { + verticalLineRect = mZoomPopup.frame; + verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; + verticalLineRect.size.width = 1.0; + if (NSIntersectsRect(rect, verticalLineRect)) { + [lineColor set]; + NSRectFill(verticalLineRect); + } + } + + if (mDisplayMask & IBShowCaretPosition) { + verticalLineRect = mCaretPositionLabel.frame; + verticalLineRect.origin.x += verticalLineRect.size.width + 1.0; + verticalLineRect.size.width = 1.0; + if (NSIntersectsRect(rect, verticalLineRect)) { + [lineColor set]; + NSRectFill(verticalLineRect); + } + } } //-------------------------------------------------------------------------------------------------- -- (BOOL) isOpaque -{ - return YES; +- (BOOL) isOpaque { + return YES; } //-------------------------------------------------------------------------------------------------- @@ -283,46 +264,38 @@ static float BarFontSize = 10.0; /** * Used to reposition our content depending on the size of the view. */ -- (void) setFrame: (NSRect) newFrame -{ - super.frame = newFrame; - [self positionSubViews]; +- (void) setFrame: (NSRect) newFrame { + super.frame = newFrame; + [self positionSubViews]; } //-------------------------------------------------------------------------------------------------- -- (void) positionSubViews -{ - NSRect currentBounds = {{0, 0}, {0, self.frame.size.height}}; - if (mDisplayMask & IBShowZoom) - { - [mZoomPopup setHidden: NO]; - currentBounds.size.width = mZoomPopup.frame.size.width; - mZoomPopup.frame = currentBounds; - currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator. - } - else - [mZoomPopup setHidden: YES]; - - if (mDisplayMask & IBShowCaretPosition) - { - [mCaretPositionLabel setHidden: NO]; - currentBounds.size.width = mCaretPositionLabel.frame.size.width; - mCaretPositionLabel.frame = currentBounds; - currentBounds.origin.x += currentBounds.size.width + 1; - } - else - [mCaretPositionLabel setHidden: YES]; - - if (mDisplayMask & IBShowStatusText) - { - // The status text always takes the rest of the available space. - [mStatusTextLabel setHidden: NO]; - currentBounds.size.width = self.frame.size.width - currentBounds.origin.x; - mStatusTextLabel.frame = currentBounds; - } - else - [mStatusTextLabel setHidden: YES]; +- (void) positionSubViews { + NSRect currentBounds = {{0, 0}, {0, self.frame.size.height}}; + if (mDisplayMask & IBShowZoom) { + [mZoomPopup setHidden: NO]; + currentBounds.size.width = mZoomPopup.frame.size.width; + mZoomPopup.frame = currentBounds; + currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator. + } else + [mZoomPopup setHidden: YES]; + + if (mDisplayMask & IBShowCaretPosition) { + [mCaretPositionLabel setHidden: NO]; + currentBounds.size.width = mCaretPositionLabel.frame.size.width; + mCaretPositionLabel.frame = currentBounds; + currentBounds.origin.x += currentBounds.size.width + 1; + } else + [mCaretPositionLabel setHidden: YES]; + + if (mDisplayMask & IBShowStatusText) { + // The status text always takes the rest of the available space. + [mStatusTextLabel setHidden: NO]; + currentBounds.size.width = self.frame.size.width - currentBounds.origin.x; + mStatusTextLabel.frame = currentBounds; + } else + [mStatusTextLabel setHidden: YES]; } //-------------------------------------------------------------------------------------------------- @@ -332,14 +305,12 @@ static float BarFontSize = 10.0; * * @param display Bitwise ORed IBDisplay values which determine what to show on the bar. */ -- (void) setDisplay: (IBDisplay) display -{ - if (mDisplayMask != display) - { - mDisplayMask = display; - [self positionSubViews]; - self.needsDisplay = YES; - } +- (void) setDisplay: (IBDisplay) display { + if (mDisplayMask != display) { + mDisplayMask = display; + [self positionSubViews]; + self.needsDisplay = YES; + } } //-------------------------------------------------------------------------------------------------- @@ -347,53 +318,43 @@ static float BarFontSize = 10.0; /** * Handler for selection changes in the zoom menu. */ -- (void) zoomItemAction: (id) sender -{ - NSNumber* selectedFactorObject = [[sender selectedCell] representedObject]; - - if (selectedFactorObject == nil) - { - NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported."); - return; - } - else - { - [self setScaleFactor: selectedFactorObject.floatValue adjustPopup: NO]; - } +- (void) zoomItemAction: (id) sender { + NSNumber *selectedFactorObject = [[sender selectedCell] representedObject]; + + if (selectedFactorObject == nil) { + NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported."); + return; + } else { + [self setScaleFactor: selectedFactorObject.floatValue adjustPopup: NO]; + } } //-------------------------------------------------------------------------------------------------- -- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag -{ - if (mScaleFactor != newScaleFactor) - { - mScaleFactor = newScaleFactor; - if (flag) - { - unsigned count = 0; - unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float); - - // We only work with some preset zoom values. If the given value does not correspond - // to one then show no selection. - while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07)) - count++; - if (count == numberOfDefaultItems) - [mZoomPopup selectItemAtIndex: -1]; - else - { - [mZoomPopup selectItemAtIndex: count]; - - // Set scale factor to found preset value if it comes close. - mScaleFactor = DefaultScaleMenuFactors[count]; - } - } - else - { - // Internally set. Notify owner. - [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor]; - } - } +- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag { + if (mScaleFactor != newScaleFactor) { + mScaleFactor = newScaleFactor; + if (flag) { + unsigned count = 0; + unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float); + + // We only work with some preset zoom values. If the given value does not correspond + // to one then show no selection. + while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07)) + count++; + if (count == numberOfDefaultItems) + [mZoomPopup selectItemAtIndex: -1]; + else { + [mZoomPopup selectItemAtIndex: count]; + + // Set scale factor to found preset value if it comes close. + mScaleFactor = DefaultScaleMenuFactors[count]; + } + } else { + // Internally set. Notify owner. + [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor]; + } + } } //-------------------------------------------------------------------------------------------------- @@ -401,19 +362,17 @@ static float BarFontSize = 10.0; /** * Called from the notification method to update the caret position display. */ -- (void) setCaretPosition: (NSPoint) position -{ - // Make the position one-based. - int newX = (int) position.x + 1; - int newY = (int) position.y + 1; - - if (mCurrentCaretX != newX || mCurrentCaretY != newY) - { - mCurrentCaretX = newX; - mCurrentCaretY = newY; - - mCaretPositionLabel.stringValue = [NSString stringWithFormat: @"%d:%d", newX, newY]; - } +- (void) setCaretPosition: (NSPoint) position { + // Make the position one-based. + int newX = (int) position.x + 1; + int newY = (int) position.y + 1; + + if (mCurrentCaretX != newX || mCurrentCaretY != newY) { + mCurrentCaretX = newX; + mCurrentCaretY = newY; + + mCaretPositionLabel.stringValue = [NSString stringWithFormat: @"%d:%d", newX, newY]; + } } //-------------------------------------------------------------------------------------------------- @@ -421,20 +380,19 @@ static float BarFontSize = 10.0; /** * Makes the bar resize to the smallest width that can accommodate the currently enabled items. */ -- (void) sizeToFit -{ - NSRect frame = self.frame; - frame.size.width = 0; - if (mDisplayMask & IBShowZoom) - frame.size.width += mZoomPopup.frame.size.width; +- (void) sizeToFit { + NSRect frame = self.frame; + frame.size.width = 0; + if (mDisplayMask & IBShowZoom) + frame.size.width += mZoomPopup.frame.size.width; - if (mDisplayMask & IBShowCaretPosition) - frame.size.width += mCaretPositionLabel.frame.size.width; + if (mDisplayMask & IBShowCaretPosition) + frame.size.width += mCaretPositionLabel.frame.size.width; - if (mDisplayMask & IBShowStatusText) - frame.size.width += mStatusTextLabel.frame.size.width; + if (mDisplayMask & IBShowStatusText) + frame.size.width += mStatusTextLabel.frame.size.width; - self.frame = frame; + self.frame = frame; } @end |
