Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Classes/TimeChartView.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 195 - (show annotations) (download)
Sun Mar 29 11:19:06 2020 UTC (4 years, 2 months ago) by toshinagata1964
File size: 21743 byte(s)
Handling of editing range is improved (especially empty time range is selected in TimeChartView)
1 //
2 // TimeChartView.m
3 // Created by Toshi Nagata on Sat Jan 25 2003.
4 //
5 /*
6 Copyright (c) 2003-2016 Toshi Nagata. All rights reserved.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 */
17
18 #import "TimeChartView.h"
19 #import "GraphicWindowController.h"
20 #import "MyDocument.h"
21 #import "MyAppController.h"
22 #import "MyMIDISequence.h"
23 #import "MDObjects.h"
24 #import "NSStringAdditions.h"
25 #import <math.h>
26 #import "MDHeaders.h"
27 #import "NSCursorAdditions.h"
28 #import "PlayingViewController.h"
29
30 typedef struct TimeScalingRecord {
31 MDTickType startTick; /* Start tick of the time region to be scaled */
32 MDTickType endTick; /* End tick of the time region to be scaled */
33 MDTickType newEndTick; /* End tick after scaling the time region */
34 int ntracks; /* Number of editable tracks */
35 int *trackNums; /* Track numbers */
36 int32_t *startPos; /* Start positions for each track to modify ticks */
37 MDTickType **originalTicks; /* Arrays of original ticks for each track */
38 IntGroup *meterPos; /* The position of meter events */
39 IntGroup *origMeterPos; /* The _original_ position of meter events */
40 } TimeScalingRecord;
41
42 @implementation TimeChartView
43
44 //- (BOOL)willChangeSelectionOnMouseDown
45 //{
46 // return NO;
47 //}
48
49 + (float)minHeight
50 {
51 return 36.0f;
52 }
53
54 - (int)clientViewType
55 {
56 return kGraphicTimeChartViewType;
57 }
58
59 //- (id)initWithFrame: (NSRect)rect
60 //{
61 // self = [super initWithFrame: rect];
62 // if (self) {
63 // selectMode = kGraphicClientIbeamMode;
64 // }
65 // return self;
66 //}
67
68 - (void)drawContentsInRect: (NSRect)aRect
69 {
70 float ppt;
71 MDTickType beginTick, endTick;
72 float originx;
73 float limitx;
74 float basey, maxLabelWidth;
75 NSPoint pt1, pt2;
76 NSRect visibleRect = [self visibleRect];
77 float editingRangeStartX, editingRangeEndX;
78
79 basey = visibleRect.origin.y + 0.5f;
80 ppt = [dataSource pixelsPerTick];
81 limitx = [dataSource sequenceDurationInQuarter] * [dataSource pixelsPerQuarter];
82
83 [self paintEditingRange: aRect startX: &editingRangeStartX endX: &editingRangeEndX];
84
85 /* Draw horizontal axis */
86 [NSBezierPath strokeLineFromPoint: NSMakePoint(aRect.origin.x, basey) toPoint: NSMakePoint(aRect.origin.x + aRect.size.width, basey)];
87
88 /* Draw ticks, labels, and time signatures */
89 maxLabelWidth = [@"0000:00:0000" sizeWithAttributes: nil].width;
90 originx = aRect.origin.x - maxLabelWidth;
91 if (originx < 0.0f)
92 originx = 0.0f;
93 beginTick = originx / ppt;
94 endTick = (aRect.origin.x + aRect.size.width) / ppt + 1;
95 while (beginTick < endTick) {
96 int mediumCount, majorCount, i, numLines;
97 int sigNumerator, sigDenominator;
98 MDEvent *sig1, *sig2;
99 MDTickType sigTick, nextSigTick;
100 float interval, startx;
101 float widthPerBeat, widthPerMeasure;
102 [dataSource verticalLinesFromTick: beginTick timeSignature: &sig1 nextTimeSignature: &sig2 lineIntervalInPixels: &interval mediumCount: &mediumCount majorCount: &majorCount];
103 sigTick = (sig1 == NULL ? 0 : MDGetTick(sig1));
104 nextSigTick = (sig2 == NULL ? kMDMaxTick : MDGetTick(sig2));
105 if (nextSigTick > endTick)
106 nextSigTick = endTick;
107 startx = sigTick * ppt;
108 sigDenominator = (sig1 == NULL ? 4 : (1 << (int)(MDGetMetaDataPtr(sig1)[1])));
109 sigNumerator = (sig1 == NULL ? 4 : MDGetMetaDataPtr(sig1)[0]);
110 if (sigNumerator == 0)
111 sigNumerator = 4;
112 [[NSString stringWithFormat: @"%d/%d", sigNumerator, sigDenominator] drawAtPoint: NSMakePoint(startx, basey + 22.0f) withAttributes: nil clippingRect: aRect];
113 numLines = (int)floor((nextSigTick - sigTick) * ppt / interval) + 1;
114 i = (startx >= originx ? 0 : (int)floor((originx - startx) / interval));
115 [[NSColor blackColor] set];
116 for ( ; i < numLines; i++) {
117 pt1 = NSMakePoint((CGFloat)(floor(startx + i * interval) + 0.5), basey);
118 pt2.x = pt1.x;
119 if (pt1.x > limitx)
120 [[NSColor grayColor] set];
121 if (i % majorCount == 0) {
122 /* Draw label */
123 NSString *label;
124 int32_t n1, n2, n3;
125 [dataSource convertTick: (MDTickType)floor((startx + i * interval) / ppt + 0.5) toMeasure: &n1 beat: &n2 andTick: &n3];
126 widthPerBeat = [(MyDocument *)[dataSource document] timebase] * ppt * 4 / sigDenominator;
127 widthPerMeasure = widthPerBeat * sigNumerator;
128 if (interval * majorCount >= widthPerMeasure) {
129 label = [NSString stringWithFormat: @"%d", (int)n1];
130 } else if (interval * majorCount >= widthPerBeat) {
131 // The major tick interval >= beat
132 label = [NSString stringWithFormat: @"%d:%d", (int)n1, (int)n2];
133 } else {
134 // The major tick interval < beat
135 label = [NSString stringWithFormat: @"%d:%d:%d", (int)n1, (int)n2, (int)n3];
136 }
137 [label drawAtPoint: NSMakePoint((CGFloat)floor(pt1.x), (CGFloat)floor(pt1.y + 10.0)) withAttributes: nil clippingRect: aRect];
138 }
139 if (pt1.x >= aRect.origin.x && pt1.x <= aRect.origin.x + aRect.size.width) {
140 /* Draw axis marks */
141 if (i % majorCount == 0) {
142 pt2.y = pt1.y + 9.0f;
143 } else if (i % mediumCount == 0)
144 pt2.y = pt1.y + 6.0f;
145 else pt2.y = pt1.y + 3.0f;
146 [NSBezierPath strokeLineFromPoint: pt1 toPoint: pt2];
147 }
148 }
149 beginTick = nextSigTick;
150 }
151 /* Draw selection range symbols */
152 [[NSColor blackColor] set];
153 if (editingRangeStartX >= 0) {
154 static NSImage *sStartEditingImage = nil;
155 static NSImage *sEndEditingImage = nil;
156 if (sStartEditingImage == nil) {
157 sStartEditingImage = [[NSImage allocWithZone: [self zone]] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"StartEditingRange.png" ofType: nil]];
158 }
159 if (sEndEditingImage == nil) {
160 sEndEditingImage = [[NSImage allocWithZone: [self zone]] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"EndEditingRange.png" ofType: nil]];
161 }
162 pt1.x = editingRangeStartX - 5.0f;
163 pt1.y = visibleRect.origin.y + 1.0f;
164 if (pt1.x >= aRect.origin.x && pt1.x < aRect.origin.x + aRect.size.width) {
165 [sStartEditingImage drawAtPoint: pt1 fromRect: NSZeroRect operation: NSCompositeSourceAtop fraction: 1.0f];
166 }
167 pt1.x = editingRangeEndX;
168 if (pt1.x >= aRect.origin.x && pt1.x < aRect.origin.x + aRect.size.width) {
169 [sEndEditingImage drawAtPoint: pt1 fromRect: NSZeroRect operation: NSCompositeSourceAtop fraction: 1.0f];
170 }
171 }
172
173 /* Draw end-of-track symbol */
174 if (aRect.origin.x + aRect.size.width > limitx) {
175 float defaultLineWidth;
176 pt1.x = pt2.x = limitx;
177 pt1.y = basey;
178 pt2.y = basey + 12.0f;
179 [NSBezierPath strokeLineFromPoint: pt1 toPoint: pt2];
180 defaultLineWidth = [NSBezierPath defaultLineWidth];
181 [NSBezierPath setDefaultLineWidth: 2.0f];
182 pt1.x = pt2.x += 3.0f;
183 [NSBezierPath strokeLineFromPoint: pt1 toPoint: pt2];
184 [NSBezierPath setDefaultLineWidth: defaultLineWidth];
185 }
186
187 // if ([self isDragging])
188 [self drawSelectRegion];
189
190 }
191
192 // Examine whether the mouse pointer is on one of the editing range marks
193 // Return value: -1, start pos, 0: none, 1: end pos
194 // pt should be in view coordinates
195 - (int)isMouseOnEditStartPositions:(NSPoint)pt
196 {
197 NSRect visibleRect = [self visibleRect];
198 if (pt.y >= visibleRect.origin.y && pt.y <= visibleRect.origin.y + 5) {
199 MDTickType startTick, endTick;
200 float startx, endx;
201 float ppt = [dataSource pixelsPerTick];
202 [(MyDocument *)[dataSource document] getEditingRangeStart: &startTick end: &endTick];
203 if (startTick >= 0 && startTick < kMDMaxTick && endTick >= startTick) {
204 startx = (float)floor(startTick * ppt);
205 endx = (float)floor(endTick * ppt);
206 if (startx - 5 <= pt.x && pt.x <= startx)
207 return -1;
208 if (endx <= pt.x && pt.x <= endx + 5)
209 return 1;
210 }
211 }
212 return 0;
213 }
214
215 /* See also: -[MyDocument scaleSelectedTime:] */
216 - (void)scaleSelectedTimeWithEvent: (NSEvent *)theEvent
217 {
218 MDSequence *seq;
219 int i, j;
220 if (timeScaling == NULL)
221 return; /* Do nothing */
222 if (theEvent == NULL)
223 timeScaling->newEndTick = timeScaling->endTick; /* Return to the original */
224 else {
225 NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil];
226 float ppt = [dataSource pixelsPerTick];
227 timeScaling->newEndTick = mousePt.x / ppt;
228 if (timeScaling->newEndTick < timeScaling->startTick)
229 timeScaling->newEndTick = timeScaling->startTick;
230 }
231 seq = [[[dataSource document] myMIDISequence] mySequence];
232 for (i = 0; i < timeScaling->ntracks; i++) {
233 int n;
234 MDPointer *pt;
235 MDEvent *ep;
236 int trackNum = timeScaling->trackNums[i];
237 MDTrack *track = MDSequenceGetTrack(seq, trackNum);
238 MDTrack *meterTrack = NULL;
239 if (trackNum == 0 && IntGroupGetCount(timeScaling->meterPos) > 0) {
240 /* Temporarily remove the meter events */
241 MDTrackUnmerge(track, &meterTrack, timeScaling->meterPos);
242 }
243 n = MDTrackGetNumberOfEvents(track) - timeScaling->startPos[i]; /* Number of events */
244 pt = MDPointerNew(track);
245 MDPointerSetPosition(pt, timeScaling->startPos[i]);
246 for (ep = MDPointerCurrent(pt), j = 0; ; ep = MDPointerForward(pt), j++) {
247 MDTickType tick = timeScaling->originalTicks[i][j];
248 if (timeScaling->newEndTick != timeScaling->endTick) {
249 if (tick < timeScaling->endTick)
250 tick = timeScaling->startTick + (MDTickType)((double)(tick - timeScaling->startTick) * (timeScaling->newEndTick - timeScaling->startTick) / (timeScaling->endTick - timeScaling->startTick));
251 else
252 tick += (timeScaling->newEndTick - timeScaling->endTick);
253 }
254 if (ep == NULL) {
255 MDTrackSetDuration(track, tick);
256 break;
257 } else {
258 MDSetTick(ep, tick);
259 }
260 }
261 if (trackNum == 0 && IntGroupGetCount(timeScaling->meterPos) > 0) {
262 /* Restore the meter events */
263 if (theEvent == NULL) {
264 /* Restore to the original positions */
265 MDTrackMerge(track, meterTrack, &(timeScaling->origMeterPos));
266 } else {
267 /* Restore to the appropriate positions */
268 IntGroupRelease(timeScaling->meterPos);
269 timeScaling->meterPos = NULL;
270 MDTrackMerge(track, meterTrack, &(timeScaling->meterPos));
271 }
272 MDTrackRelease(meterTrack);
273 MDSequenceResetCalibrators(seq);
274 }
275 }
276 [dataSource reloadClientViews];
277 }
278
279 - (void)doMouseDown: (NSEvent *)theEvent
280 {
281 NSPoint pt = [self convertPoint:[theEvent locationInWindow] fromView:nil];
282 int n = [self isMouseOnEditStartPositions:pt];
283 if (n != 0) {
284 /* Mofity selectPoints so that the 'other' edit start/end position
285 looks like the dragging start points */
286 MDTickType startTick, endTick;
287 float ppt = [dataSource pixelsPerTick];
288 [(MyDocument *)[dataSource document] getEditingRangeStart: &startTick end: &endTick];
289 if (n < 0)
290 pt.x = endTick * ppt;
291 else
292 pt.x = startTick * ppt;
293 [selectPoints replaceObjectAtIndex: 0 withObject: [NSValue valueWithPoint:pt]];
294 if (n == 1 && ([theEvent modifierFlags] & (NSAlternateKeyMask | NSShiftKeyMask)) && startTick < endTick) {
295 /* Scale selected time: initialize the internal information */
296 int i, j;
297 int32_t trackNo;
298 MDTrack *track;
299 MDSequence *seq = [[[dataSource document] myMIDISequence] mySequence];
300 timeScaling = (TimeScalingRecord *)calloc(sizeof(TimeScalingRecord), 1);
301 timeScaling->startTick = startTick;
302 timeScaling->endTick = endTick;
303 j = MDSequenceGetNumberOfTracks(seq);
304 timeScaling->trackNums = (int *)calloc(sizeof(int), j);
305 for (i = 0; (trackNo = [self sortedTrackNumberAtIndex: i]) >= 0; i++) {
306 if (![self isFocusTrack:trackNo])
307 continue;
308 timeScaling->trackNums[timeScaling->ntracks] = trackNo;
309 timeScaling->ntracks++;
310 }
311 timeScaling->trackNums = (int *)realloc(timeScaling->trackNums, sizeof(int) * timeScaling->ntracks);
312 timeScaling->startPos = (int32_t *)calloc(sizeof(int32_t), timeScaling->ntracks);
313 timeScaling->originalTicks = (MDTickType **)calloc(sizeof(MDTickType *), timeScaling->ntracks);
314 for (i = 0; i < timeScaling->ntracks; i++) {
315 MDPointer *pt;
316 MDEvent *ep;
317 int trackNum = timeScaling->trackNums[i];
318 track = MDSequenceGetTrack(seq, trackNum);
319 pt = MDPointerNew(track);
320 if (trackNum == 0) {
321 /* Conductor track: the meter events should be fixed */
322 timeScaling->meterPos = IntGroupNew();
323 }
324 if (MDPointerJumpToTick(pt, startTick)) {
325 timeScaling->startPos[i] = MDPointerGetPosition(pt);
326 } else {
327 timeScaling->startPos[i] = MDTrackGetNumberOfEvents(track);
328 }
329 timeScaling->originalTicks[i] = (MDTickType *)calloc(sizeof(MDTickType), MDTrackGetNumberOfEvents(track) - timeScaling->startPos[i] + 1); /* +1 for end-of-track */
330 for (ep = MDPointerCurrent(pt), j = 0; ep != NULL; ep = MDPointerForward(pt)) {
331 if (trackNum == 0 && MDGetKind(ep) == kMDEventTimeSignature) {
332 /* Record the position of the meter events */
333 IntGroupAdd(timeScaling->meterPos, MDPointerGetPosition(pt), 1);
334 } else {
335 timeScaling->originalTicks[i][j++] = MDGetTick(ep);
336 }
337 }
338 MDPointerRelease(pt);
339 timeScaling->originalTicks[i][j] = MDTrackGetDuration(track);
340 if (trackNum == 0) {
341 timeScaling->origMeterPos = IntGroupNew();
342 IntGroupCopy(timeScaling->origMeterPos, timeScaling->meterPos);
343 }
344 }
345 }
346 } else {
347 [super doMouseDown: theEvent];
348 }
349 }
350
351 - (int)modifyLocalGraphicTool:(int)originalGraphicTool
352 {
353 if (originalGraphicTool == kGraphicRectangleSelectTool || originalGraphicTool == kGraphicPencilTool)
354 originalGraphicTool = kGraphicIbeamSelectTool;
355 return originalGraphicTool;
356 }
357
358 - (void)doMouseDragged: (NSEvent *)theEvent
359 {
360 if (timeScaling != NULL) {
361 [self scaleSelectedTimeWithEvent:theEvent];
362 [(MyDocument *)[dataSource document] setEditingRangeStart:timeScaling->startTick end:timeScaling->newEndTick];
363 return;
364 }
365
366 [super doMouseDragged: theEvent];
367 if (selectionPath != nil) {
368 int i;
369 GraphicClientView *view;
370 NSRect rect;
371
372 rect = [selectionPath bounds];
373
374 /* Set the selection paths for other clientViews */
375 for (i = 1; (view = [dataSource clientViewAtIndex: i]) != nil; i++) {
376 NSRect viewRect = [view bounds];
377 rect.origin.y = viewRect.origin.y - 1.0f;
378 rect.size.height = viewRect.size.height + 2.0f;
379 [view setSelectRegion: [NSBezierPath bezierPathWithRect: rect]];
380 }
381 }
382 }
383
384 - (void)doMouseUp: (NSEvent *)theEvent
385 {
386 NSPoint pt1, pt2;
387 MDTickType tick1, tick2;
388 int i;
389 int32_t trackNo;
390 GraphicClientView *view;
391 BOOL shiftDown = (([theEvent modifierFlags] & NSShiftKeyMask) != 0);
392 MyDocument *document = (MyDocument *)[dataSource document];
393 float ppt = [dataSource pixelsPerTick];
394
395 /* Clear the selection paths for other clientViews */
396 for (i = 1; (view = [dataSource clientViewAtIndex: i]) != nil; i++) {
397 [view setSelectRegion: nil];
398 }
399
400 if (timeScaling != NULL) {
401 /* Time scaling */
402 /* If this is the first call since start, ask the user whether
403 she wants to insert tempo. */
404 static BOOL sFirstInvocation = YES;
405 int insertTempo = 0;
406 NSString *str = MyAppCallback_getObjectGlobalSettings(@"scale_selected_time_dialog.insert_tempo");
407 NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil];
408 if (str == nil) {
409 insertTempo = 0;
410 } else if (strtol([str UTF8String], NULL, 0) == 0) {
411 insertTempo = 0;
412 } else insertTempo = 1;
413 if (sFirstInvocation) {
414 NSAlert *alert = [[NSAlert alloc] init];
415 int response;
416 [alert setMessageText:[NSString stringWithFormat:@"Tempo events %s inserted to keep timings. OK?", (insertTempo ? "ARE" : "are NOT")]];
417 [alert setInformativeText:@"This setting can be changed anytime by 'Scale Selected Time' dialog."];
418 [alert addButtonWithTitle:[NSString stringWithFormat:@"OK, %s insert", (insertTempo ? "do" : "don't")]];
419 [alert addButtonWithTitle:@"Cancel"];
420 [alert addButtonWithTitle:[NSString stringWithFormat:@"NO, %s insert", (insertTempo ? "don't" : "do")]];
421 [alert setAlertStyle:NSWarningAlertStyle];
422 response = (int)[alert runModal];
423 [alert autorelease];
424 if (response == NSAlertThirdButtonReturn) {
425 insertTempo = !insertTempo;
426 MyAppCallback_setObjectGlobalSettings(@"scale_selected_time_dialog.insert_tempo", [NSString stringWithFormat:@"%d", insertTempo]);
427
428 } else if (response == NSAlertSecondButtonReturn) {
429 return;
430 }
431 sFirstInvocation = NO;
432 }
433 /* Register undo for selections and editing range */
434 /* [document getEditingRangeStart: &tick1 end: &tick2]; */
435 [[[self undoManager] prepareWithInvocationTarget:document]
436 setEditingRangeStart:timeScaling->startTick end:timeScaling->endTick];
437
438 /* Revert temporary scaling */
439 [self scaleSelectedTimeWithEvent:nil];
440 IntGroupRelease(timeScaling->meterPos);
441 IntGroupRelease(timeScaling->origMeterPos);
442 timeScaling->meterPos = NULL;
443 timeScaling->origMeterPos = NULL;
444
445 /* Scale time with undo registration */
446 timeScaling->newEndTick = mousePt.x / ppt;
447 if (timeScaling->newEndTick < timeScaling->startTick)
448 return;
449 [document scaleTimeFrom:timeScaling->startTick to:timeScaling->endTick newDuration:timeScaling->newEndTick - timeScaling->startTick insertTempo:insertTempo setSelection:NO];
450 tick1 = timeScaling->startTick;
451 tick2 = timeScaling->newEndTick;
452 for (i = 0; i < timeScaling->ntracks; i++)
453 free(timeScaling->originalTicks[i]);
454 free(timeScaling->originalTicks);
455 free(timeScaling->startPos);
456 free(timeScaling->trackNums);
457 free(timeScaling);
458 timeScaling = NULL;
459 return;
460
461 } else {
462
463 if (isLoupeDragging) {
464 [super doMouseUp: theEvent];
465 return;
466 }
467
468 /* Editing range */
469 pt1 = [[selectPoints objectAtIndex: 0] pointValue];
470 if (isDragging) {
471 pt2 = [[selectPoints objectAtIndex: 1] pointValue];
472 } else pt2 = pt1;
473 tick1 = (MDTickType)floor(pt1.x / ppt);
474 tick2 = (MDTickType)floor(pt2.x / ppt);
475 if (tick1 < 0)
476 tick1 = 0;
477 if (tick2 < 0)
478 tick2 = 0;
479 if (tick1 > tick2) {
480 MDTickType tick3 = tick1;
481 tick1 = tick2;
482 tick2 = tick3;
483 }
484 }
485
486 if (tick1 < tick2) {
487 /* Select all events within this tick range */
488 for (i = 0; (trackNo = [self sortedTrackNumberAtIndex: i]) >= 0; i++) {
489 MDTrack *track;
490 MDPointer *pt;
491 IntGroup *pset;
492 MDSelectionObject *obj;
493 int32_t pos1, pos2;
494 if (![self isFocusTrack:trackNo])
495 continue;
496 track = [[document myMIDISequence] getTrackAtIndex: trackNo];
497 if (track == NULL)
498 continue;
499 pt = MDPointerNew(track);
500 if (pt == NULL)
501 break;
502 pset = IntGroupNew();
503 if (pset == NULL)
504 break;
505 MDPointerJumpToTick(pt, tick1);
506 pos1 = MDPointerGetPosition(pt);
507 MDPointerJumpToTick(pt, tick2);
508 pos2 = MDPointerGetPosition(pt);
509 if (pos1 < pos2) {
510 if (IntGroupAdd(pset, pos1, pos2 - pos1) != kMDNoError)
511 break;
512 }
513 obj = [[MDSelectionObject allocWithZone: [self zone]] initWithMDPointSet: pset];
514 obj->track = track;
515 if (shiftDown) {
516 [document toggleSelection: obj inTrack: trackNo sender: self];
517 } else {
518 [document setSelection: obj inTrack: trackNo sender: self];
519 }
520 [obj release];
521 IntGroupRelease(pset);
522 MDPointerRelease(pt);
523 }
524 }
525
526 /* Change editing range */
527 if (shiftDown) {
528 MDTickType oldTick1, oldTick2;
529 [document getEditingRangeStart: &oldTick1 end: &oldTick2];
530 if (oldTick1 >= 0 && oldTick1 < tick1)
531 tick1 = oldTick1;
532 if (oldTick2 > tick2)
533 tick2 = oldTick2;
534 }
535 [document setEditingRangeStart: tick1 end: tick2];
536 if (tick1 == tick2 && [theEvent clickCount] >= 2)
537 [[dataSource playingViewController] setCurrentTick: tick1];
538 }
539
540 - (void)doMouseMoved: (NSEvent *)theEvent
541 {
542 NSPoint pt;
543 int n;
544 NSUInteger modifierFlags;
545 localGraphicTool = [self modifyLocalGraphicTool:[[self dataSource] graphicTool]];
546 if ([theEvent type] == NSFlagsChanged) {
547 pt = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];
548 } else {
549 pt = [self convertPoint:[theEvent locationInWindow] fromView:nil];
550 }
551 modifierFlags = [theEvent modifierFlags];
552 n = [self isMouseOnEditStartPositions:pt];
553 if (n != 0) {
554 if (n == 1 && (modifierFlags & (NSAlternateKeyMask | NSShiftKeyMask))) {
555 [[NSCursor horizontalMoveZoomCursor] set];
556 } else {
557 [[NSCursor horizontalMoveCursor] set];
558 }
559 } else {
560 if ([theEvent modifierFlags] & NSAlternateKeyMask)
561 [[NSCursor loupeCursor] set];
562 else [[NSCursor IBeamCursor] set];
563 }
564 }
565
566 - (void)doFlagsChanged:(NSEvent *)theEvent
567 {
568 [self doMouseMoved:theEvent];
569 }
570
571 @end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26