1/* TShelfView.m
2 *
3 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 *
5 * Author: Enrico Sersale <enrico@imago.ro>
6 *         Riccardo Mottola <rm@gnu.org>
7 * Date: August 2001
8 *
9 * This file is part of the GNUstep GWorkspace application
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
24 */
25
26#import <AppKit/AppKit.h>
27#import <GNUstepBase/GNUstep.h>
28
29#import "TShelfView.h"
30#import "TShelfViewItem.h"
31#import "TShelfIconsView.h"
32#import "GWorkspace.h"
33
34
35#define SPECIAL_TAB_W 54
36#define BUTTORX 25
37#define BUTTSZ 9
38#define BUTTSPACE 12
39#define TAB_H 24
40#define LAB_MARGIN 13
41#define BEZ_TAB_W 14
42
43@implementation TShelfView
44
45- (id)initWithFrame:(NSRect)rect
46{
47  self = [super initWithFrame: rect];
48
49  if (self) {
50    NSRect r = NSZeroRect;
51
52    ASSIGN (items, [NSMutableArray array]);
53
54    font = [NSFont fontWithName: @"Helvetica-Bold" size: 12];
55    if (font == nil) {
56      font = [NSFont boldSystemFontOfSize: 0];
57    }
58    RETAIN (font);
59
60    italicFont = [NSFont fontWithName: @"Helvetica-BoldOblique" size: 12];
61    if (italicFont == nil) {
62      italicFont = [NSFont boldSystemFontOfSize: 0];
63    }
64    RETAIN (italicFont);
65
66    r.size = NSMakeSize(BUTTSZ, BUTTSZ);
67    r.origin.y = rect.size.height - TAB_H + (int)((TAB_H - BUTTSZ) / 2);
68    r.origin.x = rect.size.width - (BUTTSZ * 2 + BUTTSPACE);
69
70    rewButt = [[NSButton alloc] initWithFrame: r];
71    [rewButt setButtonType: NSMomentaryLight];
72    [rewButt setBordered: NO];
73    [rewButt setTarget: self];
74    [rewButt setAction: @selector (buttonsAction:)];
75    [self addSubview: rewButt];
76    RELEASE (rewButt);
77
78    r.origin.x += BUTTSPACE;
79
80    ffButt = [[NSButton alloc] initWithFrame: r];
81    [ffButt setButtonType: NSMomentaryLight];
82    [ffButt setBordered: NO];
83    [ffButt setTarget: self];
84    [ffButt setAction: @selector (buttonsAction:)];
85    [self addSubview: ffButt];
86    RELEASE (ffButt);
87
88    [self setButtonsEnabled: NO];
89
90    lastItem = nil;
91    selected = nil;
92  }
93
94  return self;
95}
96
97- (void)dealloc
98{
99  RELEASE (items);
100  RELEASE (font);
101  RELEASE (italicFont);
102
103  [super dealloc];
104}
105
106- (void)addTabItem:(TShelfViewItem *)item
107{
108  [self insertTabItem: item atIndex: [items count]];
109}
110
111- (BOOL)insertTabItem:(TShelfViewItem *)item
112	      atIndex:(NSUInteger)index
113{
114  if (lastItem) {
115    if (index == [items count]) {
116      index--;
117    }
118    RETAIN (lastItem);
119    [items removeObject: lastItem];
120  }
121
122  [item setTShelfView: self];
123  [items insertObject: item atIndex: index];
124
125  if (lastItem) {
126    [items insertObject: lastItem atIndex: [items count]];
127    RELEASE (lastItem);
128  }
129
130  return YES;
131}
132
133- (void)setLastTabItem:(TShelfViewItem *)item
134{
135  lastItem = item;
136  [item setTShelfView: self];
137  [items insertObject: item atIndex: [items count]];
138}
139
140- (BOOL)removeTabItem:(TShelfViewItem *)item
141{
142  NSUInteger i = [items indexOfObject: item];
143
144  if ((i == NSNotFound) || (item == lastItem)) {
145    return NO;
146  }
147
148  if (item == selected) {
149    [[selected view] removeFromSuperview];
150    selected = nil;
151  }
152
153  [items removeObjectAtIndex: i];
154
155  return YES;
156}
157
158- (NSUInteger)indexOfItem:(TShelfViewItem *)item
159{
160  return [items indexOfObject: item];
161}
162
163- (TShelfViewItem *)selectedTabItem
164{
165  if ((selectedItem == NSNotFound) || ([items count] == 0)) {
166    return nil;
167  }
168
169  return [items objectAtIndex: selectedItem];
170}
171
172- (void)selectTabItem:(TShelfViewItem *)item
173{
174  TShelfIconsView *selectedView;
175
176  if (item == nil)
177    return;
178
179  if (selected != nil)
180    {
181      [selected setTabState: NSBackgroundTab];
182      selectedView = (TShelfIconsView *)[selected view];
183      if ([selectedView iconsType] == DATA_TAB) {
184	[selectedView setCurrentPBIcon: nil];
185      }
186      [[selected view] removeFromSuperview];
187    }
188
189  selected = item;
190
191  selectedItem = [items indexOfObject: selected];
192  [selected setTabState: NSSelectedTab];
193
194  selectedView = (TShelfIconsView *)[selected view];
195
196  if (selectedView != nil)
197    {
198      [self addSubview: selectedView];
199      [selectedView setFrame: [self contentRect]];
200      [selectedView resizeWithOldSuperviewSize: [selectedView frame].size];
201      [selectedView unselectOtherIcons: nil];
202      if ([selectedView iconsType] == DATA_TAB)
203	{
204	  [selectedView setCurrentPBIcon: nil];
205	}
206      [[self window] makeFirstResponder: [selected initialFirstResponder]];
207    }
208
209  [self setButtonsEnabled: (lastItem && (lastItem == selected))];
210
211  [self setNeedsDisplay: YES];
212}
213
214- (void)selectTabItemAtIndex:(NSUInteger)index
215{
216  [self selectTabItem: [items objectAtIndex: index]];
217}
218
219- (void)selectLastItem
220{
221  if (lastItem)
222    {
223      [self selectTabItem: lastItem];
224    }
225}
226
227- (NSFont *)font
228{
229  return font;
230}
231
232- (NSFont *)italicFont
233{
234  return italicFont;
235}
236
237- (NSRect)contentRect
238{
239  NSRect cRect = [self bounds];
240
241  cRect.origin.y += 1;
242  cRect.size.height -= 26.5;
243
244  return cRect;
245}
246
247void drawLeftTabBezier(NSPoint origin, float tabh,
248		       NSColor *sc, NSColor *fc, BOOL seltab)
249{
250  NSBezierPath *path = [NSBezierPath bezierPath];
251  NSPoint endp = NSMakePoint(origin.x + BEZ_TAB_W, origin.y + tabh);
252  NSPoint cp1 = NSMakePoint(origin.x + (BEZ_TAB_W / 2), origin.y);
253  NSPoint cp2 = NSMakePoint(origin.x + BEZ_TAB_W - (BEZ_TAB_W / 2), origin.y + tabh);
254
255  [path moveToPoint: origin];
256  [path curveToPoint: endp controlPoint1: cp1 controlPoint2: cp2];
257  [sc set];
258  [path stroke];
259
260  [path lineToPoint: NSMakePoint(origin.x + BEZ_TAB_W, origin.y)];
261  [path closePath];
262  [fc set];
263  [path fill];
264
265  if (seltab) {
266    path = [NSBezierPath bezierPath];
267    [path moveToPoint: origin];
268    [path lineToPoint: NSMakePoint(origin.x + BEZ_TAB_W, origin.y)];
269    [path stroke];
270  }
271}
272
273void drawRightTabBezier(NSPoint origin, float tabh,
274			NSColor *sc, NSColor *fc, BOOL seltab)
275{
276  NSBezierPath *path = [NSBezierPath bezierPath];
277  NSPoint endp = NSMakePoint(origin.x - BEZ_TAB_W, origin.y + tabh);
278  NSPoint cp1 = NSMakePoint(origin.x - (BEZ_TAB_W / 2), origin.y);
279  NSPoint cp2 = NSMakePoint(origin.x - BEZ_TAB_W + (BEZ_TAB_W / 2), origin.y + tabh);
280
281  [path moveToPoint: origin];
282  [path curveToPoint: endp controlPoint1: cp1 controlPoint2: cp2];
283  [sc set];
284  [path stroke];
285
286  [path lineToPoint: NSMakePoint(origin.x - BEZ_TAB_W, origin.y)];
287  [path closePath];
288  [fc set];
289  [path fill];
290
291  if (seltab) {
292    path = [NSBezierPath bezierPath];
293    [path moveToPoint: origin];
294    [path lineToPoint: NSMakePoint(origin.x - BEZ_TAB_W, origin.y)];
295    [path stroke];
296  }
297}
298
299- (void)drawRect:(NSRect)rect
300{
301  NSRect aRect = [self bounds];
302  NSPoint p = aRect.origin;
303  NSSize s = aRect.size;
304  NSUInteger count;
305  int itemxspace;
306  NSImage *backImage;
307  NSColor *scolor;
308  NSColor *fcolor;
309  NSPoint selp[2];
310  NSBezierPath *bpath;
311  int i;
312  NSPoint ipoint;
313
314  backImage = [[GWorkspace gworkspace] tshelfBackground];
315  if (backImage)
316    [backImage compositeToPoint: NSZeroPoint operation: NSCompositeSourceOver];
317
318  count = [items count];
319  itemxspace = (int)((aRect.size.width - SPECIAL_TAB_W) / (count - 1));
320
321  [[NSColor controlColor] set];
322  NSRectFill(NSMakeRect(p.x, p.y, s.width, s.height - TAB_H));
323
324  if (selected == NO) {
325    [self selectTabItemAtIndex: 0];
326  }
327
328  selp[0] = NSZeroPoint;
329  selp[1] = NSZeroPoint;
330
331  aRect.size.height -= TAB_H;
332
333  ipoint = NSMakePoint (0,0);
334  for (i = count - 1; i >= 0; i--)
335    {
336      TShelfViewItem *anItem = [items objectAtIndex: i];
337      NSRect r;
338
339      if (i == (count - 1))
340	{
341	  ipoint.x = (int)(aRect.size.width - SPECIAL_TAB_W);
342	  ipoint.y = aRect.size.height;
343
344	  if ([anItem tabState] == NSSelectedTab)
345	    {
346	      selp[0] = ipoint;
347	      fcolor = [NSColor controlColor];
348	    }
349	  else
350	    {
351	      fcolor = [NSColor controlBackgroundColor];
352	    }
353
354	  scolor = [NSColor whiteColor];
355
356	  drawLeftTabBezier(ipoint, TAB_H, scolor, fcolor, NO);
357
358	  r.origin.x = ipoint.x + LAB_MARGIN;
359	  r.origin.y = aRect.size.height;
360	  r.size.width = SPECIAL_TAB_W - LAB_MARGIN;
361	  r.size.height = TAB_H -1;
362
363	  bpath = [NSBezierPath bezierPath];
364	  [bpath setLineWidth: 1];
365	  [bpath moveToPoint: NSMakePoint(r.origin.x, r.origin.y + TAB_H)];
366	  [bpath relativeLineToPoint: NSMakePoint(r.size.width, 0)];
367	  [scolor set];
368	  [bpath stroke];
369
370	  [anItem drawImage: nil inRect: r];
371
372	  }
373      else
374	{
375	  ipoint.y = aRect.size.height;
376
377	  if ([anItem tabState] == NSSelectedTab)
378	    {
379	      selp[1] = NSMakePoint(ipoint.x + BEZ_TAB_W, ipoint.y);
380	      fcolor = [NSColor controlColor];
381	    }
382	  else
383	    {
384	      fcolor = [NSColor controlBackgroundColor];
385	    }
386
387      scolor = [NSColor blackColor];
388      drawRightTabBezier(NSMakePoint(ipoint.x + BEZ_TAB_W, ipoint.y),
389                                                  TAB_H, scolor, fcolor, NO);
390      ipoint.x -= itemxspace;
391
392      if (i != 0) {
393        if ([anItem tabState] == NSSelectedTab) {
394          selp[0] = ipoint;
395        }
396
397        scolor = [NSColor whiteColor];
398        drawLeftTabBezier(ipoint, TAB_H, scolor, fcolor, NO);
399
400	      r.origin.x = ipoint.x + LAB_MARGIN;
401	      r.origin.y = aRect.size.height;
402	      r.size.width = itemxspace - LAB_MARGIN;
403	      r.size.height = TAB_H -1;
404
405      } else {
406	      r.origin.x = ipoint.x;
407	      r.origin.y = aRect.size.height;
408	      r.size.width = itemxspace;
409	      r.size.height = TAB_H -1;
410      }
411
412      scolor = [NSColor whiteColor];
413
414      bpath = [NSBezierPath bezierPath];
415      [bpath setLineWidth: 1];
416      [bpath moveToPoint: NSMakePoint(r.origin.x, r.origin.y + TAB_H)];
417      [bpath relativeLineToPoint: NSMakePoint(r.size.width, 0)];
418      [scolor set];
419      [bpath stroke];
420
421	    [anItem drawLabelInRect: r];
422	  }
423	}
424
425  fcolor = [NSColor controlColor];
426
427  if (NSEqualPoints(selp[0], NSZeroPoint) == NO) {
428    scolor = [NSColor whiteColor];
429    drawLeftTabBezier(selp[0], TAB_H, scolor, fcolor, YES);
430
431    bpath = [NSBezierPath bezierPath];
432    [bpath setLineWidth: 1];
433    [bpath moveToPoint: NSMakePoint(p.x - 2, aRect.size.height)];
434    [bpath lineToPoint: selp[0]];
435    [scolor set];
436    [bpath stroke];
437  }
438
439  if (NSEqualPoints(selp[1], NSZeroPoint) == NO) {
440    scolor = [NSColor blackColor];
441    drawRightTabBezier(selp[1], TAB_H, scolor, fcolor, YES);
442
443    scolor = [NSColor whiteColor];
444    bpath = [NSBezierPath bezierPath];
445    [bpath setLineWidth: 1];
446    [bpath moveToPoint: selp[1]];
447    [bpath lineToPoint: NSMakePoint(s.width, aRect.size.height)];
448    [scolor set];
449    [bpath stroke];
450  }
451}
452
453- (BOOL)isOpaque
454{
455  return YES;
456}
457
458- (TShelfViewItem *)tabItemAtPoint:(NSPoint)point
459{
460  NSUInteger count = [items count];
461  NSUInteger i;
462
463  point = [self convertPoint: point fromView: nil];
464
465  for (i = 0; i < count; i++) {
466    TShelfViewItem *anItem = [items objectAtIndex: i];
467
468    if (NSPointInRect(point, [anItem tabRect])) {
469	    return anItem;
470    }
471  }
472
473  return nil;
474}
475
476- (TShelfViewItem *)lastTabItem
477{
478  return lastItem;
479}
480
481- (NSArray *)items
482{
483  return items;
484}
485
486- (void)buttonsAction:(id)sender
487{
488
489}
490
491- (void)setButtonsEnabled:(BOOL)enabled
492{
493  [rewButt setEnabled: enabled];
494  [ffButt setEnabled: enabled];
495
496  if (enabled) {
497    [rewButt setImage: [NSImage imageNamed: @"REWArrow.tiff"]];
498    [ffButt setImage: [NSImage imageNamed: @"FFArrow.tiff"]];
499  } else {
500    [rewButt setImage: [NSImage imageNamed: @"REWArrow_disabled.tiff"]];
501    [ffButt setImage: [NSImage imageNamed: @"FFArrow_disabled.tiff"]];
502  }
503}
504
505- (void)mouseDown:(NSEvent *)theEvent
506{
507  NSPoint location = [theEvent locationInWindow];
508  TShelfViewItem *anItem = [self tabItemAtPoint: location];
509
510  if (anItem && (anItem != selected)) {
511    [self selectTabItem: anItem];
512  }
513}
514
515- (BOOL)acceptsFirstResponder
516{
517  return YES;
518}
519
520- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent
521{
522  return YES;
523}
524
525@end
526