mirror of https://github.com/LIJI32/SameBoy.git
The Cocoa memory viewer new symbolicates the selection
This commit is contained in:
parent
ac45888a37
commit
fb3db82d42
|
@ -13,6 +13,7 @@
|
|||
#import "GBPaletteEditorController.h"
|
||||
#import "GBObjectView.h"
|
||||
#import "GBPaletteView.h"
|
||||
#import "GBHexStatusBarRepresenter.h"
|
||||
#import "NSObject+DefaultsObserver.h"
|
||||
|
||||
#define likely(x) GB_likely(x)
|
||||
|
@ -82,6 +83,7 @@ enum model {
|
|||
|
||||
NSString *_lastConsoleInput;
|
||||
HFLineCountingRepresenter *_lineRep;
|
||||
GBHexStatusBarRepresenter *_statusRep;
|
||||
|
||||
CVImageBufferRef _cameraImage;
|
||||
AVCaptureSession *_cameraSession;
|
||||
|
@ -878,7 +880,9 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
HFStringEncodingTextRepresenter *asciiRep = [[HFStringEncodingTextRepresenter alloc] init];
|
||||
HFVerticalScrollerRepresenter *scrollRep = [[HFVerticalScrollerRepresenter alloc] init];
|
||||
_lineRep = [[HFLineCountingRepresenter alloc] init];
|
||||
HFStatusBarRepresenter *statusRep = [[HFStatusBarRepresenter alloc] init];
|
||||
_statusRep = [[GBHexStatusBarRepresenter alloc] init];
|
||||
_statusRep.gb = &_gb;
|
||||
_statusRep.bankForDescription = -1;
|
||||
|
||||
_lineRep.lineNumberFormat = HFLineNumberFormatHexadecimal;
|
||||
|
||||
|
@ -888,14 +892,14 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
[_hexController addRepresenter:asciiRep];
|
||||
[_hexController addRepresenter:scrollRep];
|
||||
[_hexController addRepresenter:_lineRep];
|
||||
[_hexController addRepresenter:statusRep];
|
||||
[_hexController addRepresenter:_statusRep];
|
||||
|
||||
/* Tell the layout rep which reps it should lay out. */
|
||||
[layoutRep addRepresenter:hexRep];
|
||||
[layoutRep addRepresenter:scrollRep];
|
||||
[layoutRep addRepresenter:asciiRep];
|
||||
[layoutRep addRepresenter:_lineRep];
|
||||
[layoutRep addRepresenter:statusRep];
|
||||
[layoutRep addRepresenter:_statusRep];
|
||||
|
||||
|
||||
[(NSView *)[hexRep view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
@ -1827,6 +1831,7 @@ static bool is_path_writeable(const char *path)
|
|||
|
||||
[sender setStringValue:[NSString stringWithFormat:@"$%x", bank]];
|
||||
[(GBMemoryByteArray *)(_hexController.byteArray) setSelectedBank:bank];
|
||||
_statusRep.bankForDescription = bank;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_hexController reloadData];
|
||||
});
|
||||
|
@ -1846,33 +1851,37 @@ static bool is_path_writeable(const char *path)
|
|||
- (IBAction)hexUpdateSpace:(NSPopUpButtonCell *)sender
|
||||
{
|
||||
self.memoryBankItem.enabled = [sender indexOfSelectedItem] != GBMemoryEntireSpace;
|
||||
[_hexController setSelectedContentsRanges:@[[HFRangeWrapper withRange:HFRangeMake(0, 0)]]];
|
||||
GBMemoryByteArray *byteArray = (GBMemoryByteArray *)(_hexController.byteArray);
|
||||
[byteArray setMode:(GB_memory_mode_t)[sender indexOfSelectedItem]];
|
||||
uint16_t bank;
|
||||
uint16_t bank = -1;
|
||||
switch ((GB_memory_mode_t)[sender indexOfSelectedItem]) {
|
||||
case GBMemoryEntireSpace:
|
||||
_statusRep.baseAddress = _lineRep.valueOffset = 0;
|
||||
break;
|
||||
case GBMemoryROM:
|
||||
_lineRep.valueOffset = 0;
|
||||
_statusRep.baseAddress = _lineRep.valueOffset = 0;
|
||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, NULL, &bank);
|
||||
byteArray.selectedBank = bank;
|
||||
break;
|
||||
case GBMemoryVRAM:
|
||||
_lineRep.valueOffset = 0x8000;
|
||||
_statusRep.baseAddress = _lineRep.valueOffset = 0x8000;
|
||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_VRAM, NULL, &bank);
|
||||
byteArray.selectedBank = bank;
|
||||
break;
|
||||
case GBMemoryExternalRAM:
|
||||
_lineRep.valueOffset = 0xA000;
|
||||
_statusRep.baseAddress = _lineRep.valueOffset = 0xA000;
|
||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_CART_RAM, NULL, &bank);
|
||||
byteArray.selectedBank = bank;
|
||||
break;
|
||||
case GBMemoryRAM:
|
||||
_lineRep.valueOffset = 0xC000;
|
||||
_statusRep.baseAddress = _lineRep.valueOffset = 0xC000;
|
||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_RAM, NULL, &bank);
|
||||
byteArray.selectedBank = bank;
|
||||
break;
|
||||
}
|
||||
[self.memoryBankInput setStringValue:[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
|
||||
byteArray.selectedBank = bank;
|
||||
_statusRep.bankForDescription = bank;
|
||||
if (bank != (uint16_t)-1) {
|
||||
[self.memoryBankInput setStringValue:[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
|
||||
}
|
||||
|
||||
[_hexController reloadData];
|
||||
for (NSView *view in self.memoryView.subviews) {
|
||||
[view setNeedsDisplay:true];
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#import <Core/gb.h>
|
||||
#import <HexFiend/HFRepresenter.h>
|
||||
|
||||
|
||||
@interface GBHexStatusBarRepresenter : HFRepresenter
|
||||
@property GB_gameboy_t *gb;
|
||||
@property (nonatomic) bool useDecimalLength;
|
||||
@property (nonatomic) uint16_t bankForDescription;
|
||||
@property (nonatomic) uint16_t baseAddress;
|
||||
@end
|
|
@ -0,0 +1,220 @@
|
|||
#import "GBHexStatusBarRepresenter.h"
|
||||
#import <HexFiend/HFFunctions.h>
|
||||
|
||||
@interface GBHexStatusBarView : NSView
|
||||
{
|
||||
NSCell *_cell;
|
||||
NSSize _cellSize;
|
||||
GBHexStatusBarRepresenter *_representer;
|
||||
NSDictionary *_cellAttributes;
|
||||
bool _registeredForAppNotifications;
|
||||
}
|
||||
|
||||
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep;
|
||||
- (void)setString:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation GBHexStatusBarView
|
||||
|
||||
- (void)_sharedInitStatusBarView
|
||||
{
|
||||
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
[style setAlignment:NSCenterTextAlignment];
|
||||
style.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
_cellAttributes = @{
|
||||
NSForegroundColorAttributeName: [NSColor windowFrameTextColor],
|
||||
NSFontAttributeName: [NSFont labelFontOfSize:[NSFont smallSystemFontSize]],
|
||||
NSParagraphStyleAttributeName: style,
|
||||
};
|
||||
_cell = [[NSCell alloc] initTextCell:@""];
|
||||
[_cell setAlignment:NSCenterTextAlignment];
|
||||
[_cell setBackgroundStyle:NSBackgroundStyleRaised];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
[self _sharedInitStatusBarView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
[self _sharedInitStatusBarView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep
|
||||
{
|
||||
_representer = rep;
|
||||
}
|
||||
|
||||
- (void)setString:(NSString *)string
|
||||
{
|
||||
[_cell setAttributedStringValue:[[NSAttributedString alloc] initWithString:string attributes:_cellAttributes]];
|
||||
_cellSize = [_cell cellSize];
|
||||
[self setNeedsDisplay:true];
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)clip
|
||||
{
|
||||
NSRect bounds = [self bounds];
|
||||
NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - _cellSize.height / 2), NSWidth(bounds), _cellSize.height);
|
||||
[_cell drawWithFrame:cellRect inView:self];
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
[self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event
|
||||
{
|
||||
_representer.useDecimalLength ^= true;
|
||||
}
|
||||
|
||||
- (void)windowDidChangeKeyStatus:(NSNotification *)note
|
||||
{
|
||||
[self setNeedsDisplay:true];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !_registeredForAppNotifications);
|
||||
_registeredForAppNotifications = true;
|
||||
[self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
|
||||
[super viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
|
||||
{
|
||||
HFUnregisterViewForWindowAppearanceChanges(self, NO);
|
||||
[super viewWillMoveToWindow:newWindow];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
HFUnregisterViewForWindowAppearanceChanges(self, _registeredForAppNotifications);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GBHexStatusBarRepresenter
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSView *)createView {
|
||||
GBHexStatusBarView *view = [[GBHexStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
|
||||
[view setRepresenter:self];
|
||||
[view setAutoresizingMask:NSViewWidthSizable];
|
||||
return view;
|
||||
}
|
||||
|
||||
- (NSString *)describeLength:(unsigned long long)length
|
||||
{
|
||||
if (self.useDecimalLength) {
|
||||
return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
|
||||
}
|
||||
return [NSString stringWithFormat:@"$%llX byte%s", length, length == 1 ? "" : "s"];
|
||||
}
|
||||
|
||||
- (NSString *)describeOffset:(unsigned long long)offset isRangeEnd:(bool)isRangeEnd
|
||||
{
|
||||
if (!_gb) {
|
||||
return [NSString stringWithFormat:@"$%llX", offset];
|
||||
}
|
||||
return @(GB_debugger_describe_address(_gb, offset + _baseAddress, _bankForDescription, false, isRangeEnd));
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
|
||||
{
|
||||
return [self describeOffset:offset isRangeEnd:false];
|
||||
}
|
||||
|
||||
- (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
|
||||
{
|
||||
return [NSString stringWithFormat:@"Byte %@ selected", [self describeOffset:offset isRangeEnd:false]];
|
||||
}
|
||||
|
||||
- (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length
|
||||
{
|
||||
return [NSString stringWithFormat:@"Range %@ to %@ selected (%@)",
|
||||
[self describeOffset:range.location isRangeEnd:false],
|
||||
[self describeOffset:range.location + range.length isRangeEnd:true],
|
||||
[self describeLength:range.length]];
|
||||
}
|
||||
|
||||
|
||||
- (void)updateString
|
||||
{
|
||||
NSString *string = nil;
|
||||
HFController *controller = [self controller];
|
||||
if (controller) {
|
||||
unsigned long long length = [controller contentsLength];
|
||||
NSArray *ranges = [controller selectedContentsRanges];
|
||||
NSUInteger rangeCount = [ranges count];
|
||||
if (rangeCount == 1) {
|
||||
HFRange range = [ranges[0] HFRange];
|
||||
if (range.length == 0) {
|
||||
string = [self stringForEmptySelectionAtOffset:range.location length:length];
|
||||
}
|
||||
else if (range.length == 1) {
|
||||
string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
|
||||
}
|
||||
else {
|
||||
string = [self stringForSingleRangeSelection:range length:length];
|
||||
}
|
||||
}
|
||||
else {
|
||||
string = @"Multiple ranges selected";
|
||||
}
|
||||
}
|
||||
if (! string) string = @"";
|
||||
[[self view] setString:string];
|
||||
}
|
||||
|
||||
- (void)setUseDecimalLength:(bool)useDecimalLength
|
||||
{
|
||||
_useDecimalLength = useDecimalLength;
|
||||
[self updateString];
|
||||
}
|
||||
|
||||
- (void)setBaseAddress:(uint16_t)baseAddress
|
||||
{
|
||||
_baseAddress = baseAddress;
|
||||
[self updateString];
|
||||
}
|
||||
|
||||
- (void) setBankForDescription:(uint16_t)bankForDescription
|
||||
{
|
||||
_bankForDescription = bankForDescription;
|
||||
[self updateString];
|
||||
}
|
||||
|
||||
- (void)controllerDidChange:(HFControllerPropertyBits)bits
|
||||
{
|
||||
if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
|
||||
[self updateString];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSPoint)defaultLayoutPosition
|
||||
{
|
||||
return NSMakePoint(0, -1);
|
||||
}
|
||||
|
||||
@end
|
|
@ -2606,16 +2606,37 @@ const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr,
|
|||
|
||||
const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local);
|
||||
if (symbol) return symbol;
|
||||
if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr, false); /* Maybe the symbol incorrectly uses bank 0? */
|
||||
if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr, prefer_local); /* Maybe the symbol incorrectly uses bank 0? */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr)
|
||||
{
|
||||
const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, addr, false);
|
||||
if (symbol && symbol->addr == addr) return symbol->name;
|
||||
return NULL;
|
||||
return GB_debugger_describe_address(gb, addr, -1, true, false);
|
||||
}
|
||||
|
||||
const char *GB_debugger_describe_address(GB_gameboy_t *gb,
|
||||
uint16_t addr, uint16_t bank,
|
||||
bool exact_match, bool prefer_local)
|
||||
{
|
||||
if (bank == (uint16_t)-1) {
|
||||
bank = bank_for_addr(gb, addr);
|
||||
}
|
||||
if (exact_match) {
|
||||
const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local);
|
||||
if (symbol && symbol->addr == addr) return symbol->name;
|
||||
if (bank != 0) symbol = GB_map_find_symbol(get_symbol_map(gb, 0), addr, prefer_local); /* Maybe the symbol incorrectly uses bank 0? */
|
||||
if (symbol && symbol->addr == addr) return symbol->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return debugger_value_to_string(gb, (value_t){
|
||||
.value = addr,
|
||||
.bank = bank,
|
||||
.has_bank = true,
|
||||
}, true, prefer_local);
|
||||
}
|
||||
|
||||
/* The public version of debugger_evaluate */
|
||||
|
|
|
@ -15,6 +15,8 @@ GB_debugger_execute_command(GB_gameboy_t *gb, char *input); /* Destroys input. *
|
|||
char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */
|
||||
void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path);
|
||||
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr);
|
||||
/* Use -1 for bank to use the currently mapped bank */
|
||||
const char *GB_debugger_describe_address(GB_gameboy_t *gb, uint16_t addr, uint16_t bank, bool exact_match, bool prefer_local);
|
||||
bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */
|
||||
bool GB_debugger_is_stopped(GB_gameboy_t *gb);
|
||||
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// HFStatusBarRepresenter.h
|
||||
// HexFiend_2
|
||||
//
|
||||
// Copyright 2007 ridiculous_fish. All rights reserved.
|
||||
//
|
||||
|
||||
#import <HexFiend/HFRepresenter.h>
|
||||
|
||||
/*! @enum HFStatusBarMode
|
||||
The HFStatusBarMode enum is used to describe the format of the byte counts displayed by the status bar.
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, HFStatusBarMode) {
|
||||
HFStatusModeDecimal, ///< The status bar should display byte counts in decimal
|
||||
HFStatusModeHexadecimal, ///< The status bar should display byte counts in hexadecimal
|
||||
HFStatusModeApproximate, ///< The text should display byte counts approximately (e.g. "56.3 KB")
|
||||
HFSTATUSMODECOUNT ///< The number of modes, to allow easy cycling
|
||||
};
|
||||
|
||||
/*! @class HFStatusBarRepresenter
|
||||
@brief The HFRepresenter for the status bar.
|
||||
|
||||
HFStatusBarRepresenter is a subclass of HFRepresenter responsible for showing the status bar, which displays information like the total length of the document, or the number of selected bytes.
|
||||
*/
|
||||
@interface HFStatusBarRepresenter : HFRepresenter {
|
||||
HFStatusBarMode statusMode;
|
||||
}
|
||||
|
||||
@property (nonatomic) HFStatusBarMode statusMode;
|
||||
|
||||
@end
|
|
@ -1,240 +0,0 @@
|
|||
//
|
||||
// HFStatusBarRepresenter.m
|
||||
// HexFiend_2
|
||||
//
|
||||
// Copyright 2007 ridiculous_fish. All rights reserved.
|
||||
//
|
||||
|
||||
#import <HexFiend/HFStatusBarRepresenter.h>
|
||||
#import <HexFiend/HFFunctions.h>
|
||||
|
||||
#define kHFStatusBarDefaultModeUserDefaultsKey @"HFStatusBarDefaultMode"
|
||||
|
||||
@interface HFStatusBarView : NSView {
|
||||
NSCell *cell;
|
||||
NSSize cellSize;
|
||||
HFStatusBarRepresenter *representer;
|
||||
NSDictionary *cellAttributes;
|
||||
BOOL registeredForAppNotifications;
|
||||
}
|
||||
|
||||
- (void)setRepresenter:(HFStatusBarRepresenter *)rep;
|
||||
- (void)setString:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation HFStatusBarView
|
||||
|
||||
- (void)_sharedInitStatusBarView {
|
||||
NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
|
||||
[style setAlignment:NSCenterTextAlignment];
|
||||
cellAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor windowFrameTextColor], NSForegroundColorAttributeName, [NSFont labelFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, style, NSParagraphStyleAttributeName, nil];
|
||||
cell = [[NSCell alloc] initTextCell:@""];
|
||||
[cell setAlignment:NSCenterTextAlignment];
|
||||
[cell setBackgroundStyle:NSBackgroundStyleRaised];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
[self _sharedInitStatusBarView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
||||
HFASSERT([coder allowsKeyedCoding]);
|
||||
self = [super initWithCoder:coder];
|
||||
[self _sharedInitStatusBarView];
|
||||
return self;
|
||||
}
|
||||
|
||||
// nothing to do in encodeWithCoder
|
||||
|
||||
- (BOOL)isFlipped { return YES; }
|
||||
|
||||
- (void)setRepresenter:(HFStatusBarRepresenter *)rep {
|
||||
representer = rep;
|
||||
}
|
||||
|
||||
- (void)setString:(NSString *)string {
|
||||
[cell setAttributedStringValue:[[[NSAttributedString alloc] initWithString:string attributes:cellAttributes] autorelease]];
|
||||
cellSize = [cell cellSize];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)clip {
|
||||
USE(clip);
|
||||
NSRect bounds = [self bounds];
|
||||
// [[NSColor colorWithCalibratedWhite:(CGFloat).91 alpha:1] set];
|
||||
// NSRectFill(clip);
|
||||
|
||||
|
||||
NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - cellSize.height / 2), NSWidth(bounds), cellSize.height);
|
||||
[cell drawWithFrame:cellRect inView:self];
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
[self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
|
||||
}
|
||||
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event {
|
||||
USE(event);
|
||||
HFStatusBarMode newMode = ([representer statusMode] + 1) % HFSTATUSMODECOUNT;
|
||||
[representer setStatusMode:newMode];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:newMode forKey:kHFStatusBarDefaultModeUserDefaultsKey];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeKeyStatus:(NSNotification *)note {
|
||||
USE(note);
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow {
|
||||
HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !registeredForAppNotifications);
|
||||
registeredForAppNotifications = YES;
|
||||
[self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
|
||||
[super viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
|
||||
HFUnregisterViewForWindowAppearanceChanges(self, NO);
|
||||
[super viewWillMoveToWindow:newWindow];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
HFUnregisterViewForWindowAppearanceChanges(self, registeredForAppNotifications);
|
||||
[cell release];
|
||||
[cellAttributes release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation HFStatusBarRepresenter
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
HFASSERT([coder allowsKeyedCoding]);
|
||||
[super encodeWithCoder:coder];
|
||||
[coder encodeInt64:statusMode forKey:@"HFStatusMode"];
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
||||
HFASSERT([coder allowsKeyedCoding]);
|
||||
self = [super initWithCoder:coder];
|
||||
statusMode = (NSUInteger)[coder decodeInt64ForKey:@"HFStatusMode"];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
statusMode = [[NSUserDefaults standardUserDefaults] integerForKey:kHFStatusBarDefaultModeUserDefaultsKey];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSView *)createView {
|
||||
HFStatusBarView *view = [[HFStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
|
||||
[view setRepresenter:self];
|
||||
[view setAutoresizingMask:NSViewWidthSizable];
|
||||
return view;
|
||||
}
|
||||
|
||||
- (NSString *)describeLength:(unsigned long long)length {
|
||||
switch (statusMode) {
|
||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
|
||||
case HFStatusModeHexadecimal: return [NSString stringWithFormat:@"0x%llX byte%s", length, length == 1 ? "" : "s"];
|
||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"%@", HFDescribeByteCount(length)];
|
||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)describeOffset:(unsigned long long)offset {
|
||||
switch (statusMode) {
|
||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu", offset];
|
||||
case HFStatusModeHexadecimal: return [NSString stringWithFormat:@"0x%llX", offset];
|
||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"%@", HFDescribeByteCount(offset)];
|
||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
||||
}
|
||||
}
|
||||
|
||||
/* same as describeOffset, except we treat Approximate like Hexadecimal */
|
||||
- (NSString *)describeOffsetExcludingApproximate:(unsigned long long)offset {
|
||||
switch (statusMode) {
|
||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu", offset];
|
||||
case HFStatusModeHexadecimal:
|
||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"0x%llX", offset];
|
||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length {
|
||||
return [NSString stringWithFormat:@"%@ out of %@", [self describeOffset:offset], [self describeLength:length]];
|
||||
}
|
||||
|
||||
- (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length {
|
||||
return [NSString stringWithFormat:@"Byte %@ selected out of %@", [self describeOffset:offset], [self describeLength:length]];
|
||||
}
|
||||
|
||||
- (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length {
|
||||
return [NSString stringWithFormat:@"%@ selected at offset %@ out of %@", [self describeLength:range.length], [self describeOffsetExcludingApproximate:range.location], [self describeLength:length]];
|
||||
}
|
||||
|
||||
- (NSString *)stringForMultipleSelectionsWithLength:(unsigned long long)multipleSelectionLength length:(unsigned long long)length {
|
||||
return [NSString stringWithFormat:@"%@ selected at multiple offsets out of %@", [self describeLength:multipleSelectionLength], [self describeLength:length]];
|
||||
}
|
||||
|
||||
|
||||
- (void)updateString {
|
||||
NSString *string = nil;
|
||||
HFController *controller = [self controller];
|
||||
if (controller) {
|
||||
unsigned long long length = [controller contentsLength];
|
||||
NSArray *ranges = [controller selectedContentsRanges];
|
||||
NSUInteger rangeCount = [ranges count];
|
||||
if (rangeCount == 1) {
|
||||
HFRange range = [ranges[0] HFRange];
|
||||
if (range.length == 0) {
|
||||
string = [self stringForEmptySelectionAtOffset:range.location length:length];
|
||||
}
|
||||
else if (range.length == 1) {
|
||||
string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
|
||||
}
|
||||
else {
|
||||
string = [self stringForSingleRangeSelection:range length:length];
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned long long totalSelectionLength = 0;
|
||||
FOREACH(HFRangeWrapper *, wrapper, ranges) {
|
||||
HFRange range = [wrapper HFRange];
|
||||
totalSelectionLength = HFSum(totalSelectionLength, range.length);
|
||||
}
|
||||
string = [self stringForMultipleSelectionsWithLength:totalSelectionLength length:length];
|
||||
}
|
||||
}
|
||||
if (! string) string = @"";
|
||||
[[self view] setString:string];
|
||||
}
|
||||
|
||||
- (HFStatusBarMode)statusMode {
|
||||
return statusMode;
|
||||
}
|
||||
|
||||
- (void)setStatusMode:(HFStatusBarMode)mode {
|
||||
statusMode = mode;
|
||||
[self updateString];
|
||||
}
|
||||
|
||||
- (void)controllerDidChange:(HFControllerPropertyBits)bits {
|
||||
if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
|
||||
[self updateString];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSPoint)defaultLayoutPosition {
|
||||
return NSMakePoint(0, -1);
|
||||
}
|
||||
|
||||
@end
|
|
@ -28,7 +28,6 @@
|
|||
#import <HexFiend/HFFullMemoryByteSlice.h>
|
||||
#import <HexFiend/HFHexTextRepresenter.h>
|
||||
#import <HexFiend/HFLineCountingRepresenter.h>
|
||||
#import <HexFiend/HFStatusBarRepresenter.h>
|
||||
#import <HexFiend/HFLayoutRepresenter.h>
|
||||
#import <HexFiend/HFStringEncodingTextRepresenter.h>
|
||||
#import <HexFiend/HFVerticalScrollerRepresenter.h>
|
||||
|
|
Loading…
Reference in New Issue