API  1.0.0
CPFontPanel.j
Go to the documentation of this file.
1 /*
2  * CPFontPanel.j
3  * AppKit
4  *
5  * TODOs:
6  * 1. make browser-width for size smaller and fix columns
7  * 2. add all the missing features from the MacOS X counterpart (sampleview)
8  *
9  *
10  * Created by Daniel Boehringer on 2/JAN/2014.
11  * All modifications copyright Daniel Boehringer 2013.
12  * Extensive code formatting and review by Andrew Hankinson
13  * Based on original work by
14  * Created by Emmanuel Maillard on 06/03/2010.
15  * Copyright Emmanuel Maillard 2010.
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 
32 
33 
34 
35 
36 /*
37  Collection indexes
38 */
54  _sharedFontPanel;
55 
56 // FIXME<!> Locale support
57 var _availableTraits= [@"Normal", @"Italic", @"Bold", @"Bold Italic"],
58  _availableSizes = [@"9", @"10", @"11", @"12", @"13", @"14", @"18", @"24", @"36", @"48", @"72", @"96"];
59 
60 
64 @implementation CPFontPanel : CPPanel
65 {
66  id _fontBrowser;
67  id _traitBrowser;
68  id _sizeBrowser;
69  CPArray _availableFonts;
70  id _textColorWell;
71  CPColor _textColor;
72  int _currentColorButtonTag;
73  BOOL _setupDone;
74  int _fontChanges;
75 }
76 
77 
78 #pragma mark -
79 #pragma mark Class methods
80 
84 + (BOOL)sharedFontPanelExists
85 {
86  return _sharedFontPanel !== nil;
87 }
88 
92 + (CPFontPanel)sharedFontPanel
93 {
94  if (!_sharedFontPanel)
95  _sharedFontPanel = [[CPFontPanel alloc] init];
96 
97  return _sharedFontPanel;
98 }
99 
100 
101 #pragma mark -
102 #pragma mark Init methods
103 
105 - (id)init
106 {
107  if (self = [super initWithContentRect:CGRectMake(100, 90, 450, 394) styleMask:(CPTitledWindowMask | CPClosableWindowMask /*| CPResizableWindowMask*/ )])
108  {
110  [self setTitle:@"Font Panel"];
111  [self setLevel:CPFloatingWindowLevel];
112  [self setFloatingPanel:YES];
113  [self setBecomesKeyOnlyIfNeeded:YES];
114  [self setMinSize:CGSizeMake(378, 394)];
115 
116  _availableFonts = [[CPFontManager sharedFontManager] availableFonts];
117  _textColor = [CPColor blackColor];
118  _setupDone = NO;
119  _fontChanges = kNothingChanged;
120  }
121 
122  return self;
123 }
124 
126 - (void)_setupToolbarView
127 {
128  _toolbarView = [[CPView alloc] initWithFrame:CGRectMake(0, kBorderSpacing, CGRectGetWidth([self frame]), kToolbarHeight)];
129  [_toolbarView setAutoresizingMask:CPViewWidthSizable];
130 
131  // Text color
132  _textColorWell = [[CPColorWell alloc] initWithFrame:CGRectMake(10, 0, 25, 25)];
133  [_textColorWell setColor:_textColor];
134  [_toolbarView addSubview:_textColorWell];
135 }
136 
137 - (void)_setupBrowser:(CPBrowser)aBrowser
138 {
139  [aBrowser setTarget:self];
140  [aBrowser setAction:@selector(browserClicked:)];
141  [aBrowser setDoubleAction:@selector(dblClicked:)];
142  [aBrowser setAllowsEmptySelection:NO];
143  [aBrowser setAllowsMultipleSelection:NO];
144  [aBrowser setDelegate:self];
145  [[self contentView] addSubview:aBrowser];
146 }
147 
148 - (void)_setupContents
149 {
150  if (_setupDone)
151  return;
152 
153  _setupDone = YES;
154 
155  [self _setupToolbarView];
156 
157  var contentView = [self contentView],
158  label = [CPTextField labelWithTitle:@"Font name"],
159  contentBounds = [contentView bounds],
160  upperView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(contentBounds), CGRectGetHeight(contentBounds) - (kBorderSpacing + kToolbarHeight + kInnerSpacing))];
161 
162  [contentView addSubview:_toolbarView];
163 
164  _fontBrowser = [[CPBrowser alloc] initWithFrame:CGRectMake(10, 35, 150, 350)];
165  _traitBrowser = [[CPBrowser alloc] initWithFrame:CGRectMake(155, 35, 150, 350)];
166  _sizeBrowser = [[CPBrowser alloc] initWithFrame:CGRectMake(300, 35, 140, 350)];
167 
168  [self _setupBrowser:_fontBrowser];
169  [self _setupBrowser:_traitBrowser];
170  [self _setupBrowser:_sizeBrowser];
171 
174  name:CPTextViewDidChangeSelectionNotification
175  object:nil];
176 }
177 
178 - (void)textViewDidChangeSelection:(CPNotification)notification
179 {
180  [self _refreshWithTextView:[notification object]];
181 
182 }
183 
184 - (void)_refreshWithTextView:(CPTextView)textView
185 {
186  if (![self isVisible])
187  return;
188 
189  var attribs = [textView _attributesForFontPanel],
190  font = [attribs objectForKey:CPFontAttributeName] || [[textView textStorage] font] || [CPFont systemFontOfSize:12.0],
191  color = [attribs objectForKey:CPForegroundColorAttributeName];
192 
193  if (!font)
194  return;
195 
196  var trait = kTypefaceIndex_Normal;
197 
198  if ([font isItalic] && [font isBold])
200  else if ([font isItalic])
201  trait = kTypefaceIndex_Italic;
202  else if ([font isBold])
203  trait = kTypefaceIndex_Bold;
204 
205  [self setCurrentFont:font];
206  [self setCurrentTrait:trait];
207  [self setCurrentSize:[font size] + ""]; //cast to string
208 
209  if (!color)
210  return;
211 
212  [_textColorWell setColor:color];
213 }
214 
215 - (void)orderFront:(id)sender
216 {
217  [self _setupContents];
218  [super orderFront:sender];
219  [self _refreshWithTextView:[[CPApp keyWindow] firstResponder]];
220 }
221 
222 - (void)reloadDefaultFontFamilies
223 {
224  _availableFonts = [[CPFontManager sharedFontManager] availableFonts];
225 }
226 
227 - (BOOL)worksWhenModal
228 {
229  return YES;
230 }
231 
236 - (CPFont)panelConvertFont:(CPFont)aFont
237 {
238  var newFont = aFont,
239  index = 0;
240 
241  switch (_fontChanges)
242  {
243  case kFontNameChanged:
245  [CPDictionary dictionaryWithObject:[self currentFont] forKey:CPFontNameAttribute]] size:0.0];
246  break;
247 
248  case kTypefaceChanged:
249  index = [self currentTrait];
250  if (index == kTypefaceIndex_BoldItalic)
251  newFont = [[CPFontManager sharedFontManager] convertFont:aFont toHaveTrait:CPBoldFontMask | CPItalicFontMask];
252  else if (index == kTypefaceIndex_Bold)
253  newFont = [[CPFontManager sharedFontManager] convertFont:aFont toHaveTrait:CPBoldFontMask];
254  else if (index == kTypefaceIndex_Italic)
255  newFont = [[CPFontManager sharedFontManager] convertFont:aFont toHaveTrait:CPItalicFontMask];
256  else
257  newFont = [[CPFontManager sharedFontManager] convertFont:aFont toNotHaveTrait:CPBoldFontMask | CPItalicFontMask];
258  break;
259 
260  case kSizeChanged:
261  newFont = [[CPFontManager sharedFontManager] convertFont:aFont toSize:[self currentSize]];
262  break;
263 
264  case kNothingChanged:
265  break;
266 
267  default:
268  CPLog.trace(@"FIXME: -[" + [self className] + " " + _cmd + "] unhandled _fontChanges: " + _fontChanges);
269  break;
270  }
271 
272  return newFont;
273 }
274 
275 - (void)setCurrentSize:(CGSize)aSize
276 {
277  [_sizeBrowser selectRow:[_availableSizes indexOfObject:aSize] inColumn:0];
278 }
279 
280 - (CPString)currentSize
281 {
282  return [_sizeBrowser selectedItem];
283 }
284 
285 - (void)setCurrentFont:(CPFont)aFont
286 {
287  [_fontBrowser selectRow:[_availableFonts indexOfObject:[aFont familyName]] inColumn:0];
288 }
289 
290 - (CPString)currentFont
291 {
292  return [_fontBrowser selectedItem];
293 }
294 
295 - (void)setCurrentTrait:(unsigned)aTrait
296 {
297  var row = 0;
298 
299  switch (aTrait)
300  {
302  row = 1;
303  break;
304 
305  case kTypefaceIndex_Bold:
306  row = 2;
307  break;
308 
310  row = 3;
311  break;
312  }
313 
314  [_traitBrowser selectRow:row inColumn:0];
315 }
316 
317 // FIXME<!> Locale support
318 - (unsigned)currentTrait
319 {
320  var sel = [_traitBrowser selectedItem];
321 
322  if (sel === "Italic")
323  return kTypefaceIndex_Italic;
324 
325  if (sel === "Bold")
326  return kTypefaceIndex_Bold;
327 
328  if (sel === "Bold Italic")
330 
331  return kTypefaceIndex_Normal;
332 }
333 
339 - (void)setPanelFont:(CPFont)font isMultiple:(BOOL)flag
340 {
341  [self _setupContents];
342 
343  if ([self currentFont] !== [font familyName])
344  [self setCurrentFont:[font familyName]];
345 
346  if ([self currentSize] != [font size])
347  [self setCurrentSize:[font size]];
348 
349  var typefaceIndex = kTypefaceIndex_Normal,
350  symbolicTraits = [[font fontDescriptor] symbolicTraits];
351 
352  if ((symbolicTraits & CPFontItalicTrait) && (symbolicTraits & CPFontBoldTrait))
353  typefaceIndex = kTypefaceIndex_BoldItalic;
354  else if (symbolicTraits & CPFontItalicTrait)
355  typefaceIndex = kTypefaceIndex_Italic;
356  else if (symbolicTraits & CPFontBoldTrait)
357  typefaceIndex = kTypefaceIndex_Bold;
358 
359  if ([self currentTrait] != typefaceIndex)
360  [self setCurrentTrait:typefaceIndex ];
361 
362  _fontChanges = kNothingChanged;
363 }
364 
365 - (void)changeColor:(id)sender
366 {
367  _textColor = [sender color];
368  _fontChanges = kTextColorChanged;
370 }
371 
373 // TODO: ask CPFontManager for traits //
374 - (void)browserClicked:(id)aBrowser
375 {
376  if (aBrowser === _fontBrowser)
377  {
378  _fontChanges = kFontNameChanged;
380  }
381  else if (aBrowser === _traitBrowser)
382  {
383  _fontChanges = kTypefaceChanged;
385  }
386  else if (aBrowser === _sizeBrowser)
387  {
388  _fontChanges = kSizeChanged;
390  }
391 }
392 
393 - (void)dblClicked:(id)sender
394 {
395  // alert("DOUBLE");
396 }
397 
398 - (id)browser:(id)aBrowser numberOfChildrenOfItem:(id)anItem
399 {
400  if (aBrowser === _fontBrowser)
401  return [_availableFonts count];
402 
403  if (aBrowser === _traitBrowser)
404  return [_availableTraits count];
405 
406  return [_availableSizes count]
407 }
408 
409 - (id)browser:(id)aBrowser child:(int)index ofItem:(id)anItem
410 {
411  if (aBrowser === _fontBrowser)
412  return [_availableFonts objectAtIndex:index];
413 
414  if (aBrowser === _traitBrowser)
415  return [_availableTraits objectAtIndex:index];
416 
417  return [_availableSizes objectAtIndex:index];
418 }
419 
420 - (id)browser:(id)aBrowser objectValueForItem:(id)anItem
421 {
422  return anItem;
423 }
424 
425 - (BOOL)browser:(id)aBrowser isLeafItem:(id)anItem
426 {
427  return YES;
428 }
429 
430 @end
431 
void setCurrentFont:(CPFont aFont)
Definition: CPFontPanel.j:285
Definition: CPFont.h:2
var kFontNameChanged
Definition: CPFontPanel.j:47
void setDelegate:(id< CPBrowserDelegate > anObject)
Definition: CPBrowser.j:179
CPString currentSize()
Definition: CPFontPanel.j:280
var kSizeChanged
Definition: CPFontPanel.j:49
CPString currentFont()
Definition: CPFontPanel.j:290
var kTypefaceIndex_Bold
Definition: CPFontPanel.j:41
void setAction:(SEL anAction)
Definition: CPControl.j:282
id init()
Definition: CALayer.j:126
void setFontPanelFactory:(Class aClass)
var kToolbarHeight
Definition: CPFontPanel.j:43
void setCurrentTrait:(unsigned aTrait)
Definition: CPFontPanel.j:295
CPFont systemFontOfSize:(CGSize aSize)
Definition: CPFont.j:282
void setTarget:(id aTarget)
Definition: CPControl.j:300
var kTypefaceIndex_Normal
Definition: CPFontPanel.j:39
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
void setTitle:(CPString aTitle)
Definition: CPWindow.j:1700
var kInnerSpacing
Definition: CPFontPanel.j:45
CPString label
CPFont convertFont:toSize:(CPFont aFont, [toSize] float aSize)
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
CPTitledWindowMask
CPFont convertFont:toNotHaveTrait:(CPFont aFont, [toNotHaveTrait] CPFontTraitMask fontTrait)
CPColor blackColor()
Definition: CPColor.j:284
void orderFront:(id aSender)
Definition: CPWindow.j:925
var kNothingChanged
Definition: CPFontPanel.j:46
void setCurrentSize:(CGSize aSize)
Definition: CPFontPanel.j:275
An immutable string (collection of characters).
Definition: CPString.h:2
var kUnderlineChanged
Definition: CPFontPanel.j:52
var kTypefaceIndex_BoldItalic
Definition: CPFontPanel.j:42
var kTextColorChanged
Definition: CPFontPanel.j:50
void setAllowsMultipleSelection:(BOOL shouldAllow)
Definition: CPBrowser.j:674
CPFontDescriptor fontDescriptor()
Definition: CPFont.j:453
CPFontDescriptor fontDescriptorByAddingAttributes:(CPDictionary attributes)
unsigned currentTrait()
Definition: CPFontPanel.j:318
var kBorderSpacing
Definition: CPFontPanel.j:44
var kWeightChanged
Definition: CPFontPanel.j:53
void setFloatingPanel:(BOOL isFloatingPanel)
Definition: CPPanel.j:73
CPFontManager sharedFontManager()
Definition: CPFontManager.j:82
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPFontSymbolicTraits symbolicTraits()
void setAllowsEmptySelection:(BOOL shouldAllow)
Definition: CPBrowser.j:688
CPFontBoldTrait
CPColor colorWithWhite:alpha:(float white, [alpha] float alpha)
Definition: CPColor.j:157
CPClosableWindowMask
var kTypefaceIndex_Italic
Definition: CPFontPanel.j:40
CPFont fontWithDescriptor:size:(CPFontDescriptor fontDescriptor, [size] float aSize)
Definition: CPFont.j:444
void setBecomesKeyOnlyIfNeeded:(BOOL shouldBecomeKeyOnlyIfNeeded)
Definition: CPPanel.j:91
CPFont convertFont:toHaveTrait:(CPFont aFont, [toHaveTrait] CPFontTraitMask addTraits)
CPTextStorage textStorage()
Definition: CPTextView.j:3098
var kBackgroundColorChanged
Definition: CPFontPanel.j:51
void setLevel:(int aLevel)
Definition: CPWindow.j:1083
CPFontItalicTrait
CPTextField labelWithTitle:(CPString aTitle)
Definition: CPTextField.j:200
CPString familyName()
Definition: CPFont.j:393
Sends messages (CPNotification) between objects.
void modifyFontViaPanel:(id sender)
float size()
Definition: CPFont.j:375
void setDoubleAction:(SEL aValue)
Definition: CPBrowser.j:1204
void setBackgroundColor:(CPColor aColor)
Definition: CPView.j:1947
Class class()
Definition: CPObject.j:179
CPView contentView()
Definition: CPWindow.j:1226
Definition: CPPanel.h:2
void setMinSize:(CGSize aSize)
Definition: CPWindow.j:1272
id alloc()
Definition: CPObject.j:130
Definition: CPView.j:137
var kTypefaceChanged
Definition: CPFontPanel.j:48
id dictionaryWithObject:forKey:(id anObject, [forKey] id aKey)
Definition: CPDictionary.j:81
CPArray availableFonts()