SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
Cocoa/GBHexStatusBarRepresenter.m
1 #import "GBHexStatusBarRepresenter.h"
2 #import <HexFiend/HFFunctions.h>
3
4 @interface GBHexStatusBarView : NSView
5 {
6 NSCell *_cell;
7 NSSize _cellSize;
8 GBHexStatusBarRepresenter *_representer;
9 NSDictionary *_cellAttributes;
10 bool _registeredForAppNotifications;
11 }
12
13 - (void)setRepresenter:(GBHexStatusBarRepresenter *)rep;
14 - (void)setString:(NSString *)string;
15
16 @end
17
18
19 @implementation GBHexStatusBarView
20
21 - (void)_sharedInitStatusBarView
22 {
23 NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
24 [style setAlignment:NSCenterTextAlignment];
25 style.lineBreakMode = NSLineBreakByTruncatingTail;
26 _cellAttributes = @{
27 NSForegroundColorAttributeName: [NSColor windowFrameTextColor],
28 NSFontAttributeName: [NSFont labelFontOfSize:[NSFont smallSystemFontSize]],
29 NSParagraphStyleAttributeName: style,
30 };
31 _cell = [[NSCell alloc] initTextCell:@""];
32 [_cell setAlignment:NSCenterTextAlignment];
33 [_cell setBackgroundStyle:NSBackgroundStyleRaised];
34 }
35
36 - (instancetype)initWithFrame:(NSRect)frame
37 {
38 self = [super initWithFrame:frame];
39 [self _sharedInitStatusBarView];
40 return self;
41 }
42
43 - (instancetype)initWithCoder:(NSCoder *)coder
44 {
45 self = [super initWithCoder:coder];
46 [self _sharedInitStatusBarView];
47 return self;
48 }
49
50 - (BOOL)isFlipped
51 {
52 return true;
53 }
54
55 - (void)setRepresenter:(GBHexStatusBarRepresenter *)rep
56 {
57 _representer = rep;
58 }
59
60 - (void)setString:(NSString *)string
61 {
62 [_cell setAttributedStringValue:[[NSAttributedString alloc] initWithString:string attributes:_cellAttributes]];
63 _cellSize = [_cell cellSize];
64 [self setNeedsDisplay:true];
65 }
66
67 - (void)drawRect:(NSRect)clip
68 {
69 NSRect bounds = [self bounds];
70 NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - _cellSize.height / 2), NSWidth(bounds), _cellSize.height);
71 [_cell drawWithFrame:cellRect inView:self];
72 }
73
74 - (void)setFrame:(NSRect)frame
75 {
76 [super setFrame:frame];
77 [self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
78 }
79
80 - (void)mouseDown:(NSEvent *)event
81 {
82 _representer.useDecimalLength ^= true;
83 }
84
85 - (void)windowDidChangeKeyStatus:(NSNotification *)note
86 {
87 [self setNeedsDisplay:true];
88 }
89
90 - (void)viewDidMoveToWindow
91 {
92 HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !_registeredForAppNotifications);
93 _registeredForAppNotifications = true;
94 [self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
95 [super viewDidMoveToWindow];
96 }
97
98 - (void)viewWillMoveToWindow:(NSWindow *)newWindow
99 {
100 HFUnregisterViewForWindowAppearanceChanges(self, NO);
101 [super viewWillMoveToWindow:newWindow];
102 }
103
104 - (void)dealloc
105 {
106 HFUnregisterViewForWindowAppearanceChanges(self, _registeredForAppNotifications);
107 }
108
109 @end
110
111 @implementation GBHexStatusBarRepresenter
112
113 - (instancetype)init
114 {
115 self = [super init];
116 return self;
117 }
118
119 - (NSView *)createView {
120 GBHexStatusBarView *view = [[GBHexStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
121 [view setRepresenter:self];
122 [view setAutoresizingMask:NSViewWidthSizable];
123 return view;
124 }
125
126 - (NSString *)describeLength:(unsigned long long)length
127 {
128 if (self.useDecimalLength) {
129 return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
130 }
131 return [NSString stringWithFormat:@"$%llX byte%s", length, length == 1 ? "" : "s"];
132 }
133
134 - (NSString *)describeOffset:(unsigned long long)offset isRangeEnd:(bool)isRangeEnd
135 {
136 if (!_gb) {
137 return [NSString stringWithFormat:@"$%llX", offset];
138 }
139 return @(GB_debugger_describe_address(_gb, offset + _baseAddress, offset < 0x4000? -1 :_bankForDescription, false, isRangeEnd));
140 }
141
142
143 - (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
144 {
145 return [self describeOffset:offset isRangeEnd:false];
146 }
147
148 - (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
149 {
150 return [NSString stringWithFormat:@"Byte %@ selected", [self describeOffset:offset isRangeEnd:false]];
151 }
152
153 - (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length
154 {
155 return [NSString stringWithFormat:@"Range %@ to %@ selected (%@)",
156 [self describeOffset:range.location isRangeEnd:false],
157 [self describeOffset:range.location + range.length isRangeEnd:true],
158 [self describeLength:range.length]];
159 }
160
161
162 - (void)updateString
163 {
164 NSString *string = nil;
165 HFController *controller = [self controller];
166 if (controller) {
167 unsigned long long length = [controller contentsLength];
168 NSArray *ranges = [controller selectedContentsRanges];
169 NSUInteger rangeCount = [ranges count];
170 if (rangeCount == 1) {
171 HFRange range = [ranges[0] HFRange];
172 if (range.length == 0) {
173 string = [self stringForEmptySelectionAtOffset:range.location length:length];
174 }
175 else if (range.length == 1) {
176 string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
177 }
178 else {
179 string = [self stringForSingleRangeSelection:range length:length];
180 }
181 }
182 else {
183 string = @"Multiple ranges selected";
184 }
185 }
186 if (! string) string = @"";
187 [[self view] setString:string];
188 }
189
190 - (void)setUseDecimalLength:(bool)useDecimalLength
191 {
192 _useDecimalLength = useDecimalLength;
193 [self updateString];
194 }
195
196 - (void)setBaseAddress:(uint16_t)baseAddress
197 {
198 _baseAddress = baseAddress;
199 [self updateString];
200 }
201
202 - (void) setBankForDescription:(uint16_t)bankForDescription
203 {
204 _bankForDescription = bankForDescription;
205 [self updateString];
206 }
207
208 - (void)controllerDidChange:(HFControllerPropertyBits)bits
209 {
210 if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
211 [self updateString];
212 }
213 }
214
215 + (NSPoint)defaultLayoutPosition
216 {
217 return NSMakePoint(0, -1);
218 }
219
220 @end
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.