1require 'osx/cocoa'
2
3class BigLetterView < OSX::NSView
4  include OSX
5
6  def draggingEntered(sender)
7    log "draggingEntered:"
8    if sender.draggingSource != self then
9      pb = sender.draggingPasteboard
10      if pb.availableTypeFromArray [NSStringPboardType] then
11	@highlighted = true
12	setNeedsDisplay true
13	return NSDragOperationCopy
14      end
15    end
16    return NSDragOperationNone
17  end
18
19  def draggingExited(sender)
20    log "draggingExited:"
21    @highlighted = false
22    setNeedsDisplay true
23  end
24
25  def prepareForDragOperation(sender)
26    true
27  end
28
29  def performDragOperation(sender)
30    pb = sender.draggingPasteboard
31    unless readStringFromPasteboard(pb) then
32      log "Error: Could not read from dragging pasteboard"
33      return false
34    end
35    return true
36  end
37
38  def concludeDragOperation(sender)
39    log "concludeDragOperation:"
40    @highlighted = false
41    setNeedsDisplay true
42  end
43
44  def initWithFrame(rect)
45    super_initWithFrame(rect)
46    log "initializing view"
47    prepareAttributes
48    setBgColor NSColor.yellowColor
49    setString ""
50    @bold = false
51    @italic = false
52    @fmgr = NSFontManager.sharedFontManager
53    registerForDraggedTypes [NSStringPboardType]
54    @highlighted = false
55    self
56  end
57
58  def setBgColor(c)
59    @bgColor = c
60    setNeedsDisplay true
61  end
62
63  def setString(c)
64    c = NSString.stringWithString(c) if c.is_a? String
65    @string = c
66    log "The string is now #{@string.to_s}"
67    setNeedsDisplay true
68  end
69
70  def drawStringCenterdIn(r)
71    sorig = NSPoint.new
72    ssize = @string.sizeWithAttributes(@attributes)
73    sorig.x = r.origin.x + (r.size.width - ssize.width) / 2
74    sorig.y = r.origin.y + (r.size.height - ssize.height) / 2
75
76    font = @attributes.objectForKey(NSFontAttributeName)
77
78    mask = @bold ? NSBoldFontMask : NSUnboldFontMask
79    font = @fmgr.convertFont_toHaveTrait(font, mask)
80    @attributes.setObject_forKey(font, NSFontAttributeName)
81
82    mask = @italic ? NSItalicFontMask : NSUnitalicFontMask
83    font = @fmgr.convertFont_toHaveTrait(font, mask)
84    @attributes.setObject_forKey(font, NSFontAttributeName)
85
86    @string.drawAtPoint_withAttributes(sorig, @attributes)
87  end
88
89  def drawRect(rect)
90    b = bounds
91    (@highlighted ? NSColor.whiteColor : @bgColor).set
92    NSBezierPath.fillRect(b)
93    drawStringCenterdIn(b)
94    if window.firstResponder == self then
95      NSColor.blackColor.set
96      NSBezierPath.strokeRect(b)
97    end
98  end
99
100  def acceptsFirstResponder
101    log "Accepting"
102    true
103  end
104
105  def resignFirstResponder
106    log "Resigning"
107    setNeedsDisplay true
108    true
109  end
110
111  def becomeFirstResponder
112    log "Becoming"
113    setNeedsDisplay true
114    true
115  end
116
117  def keyDown(event)
118    input = event.characters
119    if input.isEqual? "\t" then
120      window.selectNextKeyView(nil)
121    elsif input.isEqual? "\031" then
122      window.selectPreviousKeyView(nil)
123    else
124      setString(input)
125    end
126  end
127
128  def prepareAttributes
129    @attributes = NSMutableDictionary.alloc.init
130    @attributes.
131      setObject_forKey(NSFont.fontWithName_size("Helvetica", 75),
132		       NSFontAttributeName)
133    @attributes.
134      setObject_forKey(NSSingleUnderlineStyle,
135		       NSUnderlineStyleAttributeName)
136    @attributes.
137      setObject_forKey(NSColor.redColor,
138		       NSForegroundColorAttributeName)
139  end
140
141  def savePDF(sender)
142    panel = NSSavePanel.savePanel
143    panel.setRequiredFileType "pdf"
144    panel.
145      objc_send :beginSheetForDirectory, nil,
146                                  :file, nil,
147                        :modalForWindow, window,
148                         :modalDelegate, self,
149                        :didEndSelector, "didEnd_returnCode_contextInfo_",
150                           :contextInfo, nil
151  end
152  ib_action :savePDF
153
154  def didEnd_returnCode_contextInfo(sheet, code, contextInfo)
155    if code == NSOKButton then
156      data = dataWithPDFInsideRect(bounds)
157      data.writeToFile_atomically(sheet.filename, true)
158    end
159  end
160
161  def boldClicked(sender)
162    @bold = (sender.state == NSOnState)
163    setNeedsDisplay true
164  end
165  ib_action :boldClicked
166  
167  def italicClicked(sender)
168    @italic = (sender.state == NSOnState)
169    setNeedsDisplay true
170  end
171  ib_action :italicClicked
172
173  def writePDFToPasteboard(pb)
174    types = [NSPDFPboardType]
175    pb.addTypes_owner(types, self)
176    pb.setData_forType(dataWithPDFInsideRect(bounds), types[0])
177  end
178  
179  def writeStringToPasteboard(pb)
180    types = [NSStringPboardType]
181    pb.declareTypes_owner(types, self)
182    pb.setString_forType(@string, types[0])
183  end
184  
185  def readStringFromPasteboard (pb)
186    if pb.availableTypeFromArray? [NSStringPboardType] then
187      value = pb.stringForType(NSStringPboardType)
188      value = value.to_s[0].chr if value.length > 1
189      setString(value)
190      return true
191    end
192    false
193  end
194
195  def cut(sender)
196    copy(sender)
197    setString ""
198  end
199  ib_action :cut
200
201  def copy(sender)
202    pb = NSPasteboard.generalPasteboard
203    writeStringToPasteboard(pb)
204    writePDFToPasteboard(pb)
205  end
206  ib_action :copy
207
208  def paste(sender)
209    pb = NSPasteboard.generalPasteboard
210    NSBeep unless readStringFromPasteboard(pb)
211  end
212  ib_action :paste
213
214  def draggingSourceOperationMaskForLocal(flag)
215    NSDragOperationCopy
216  end
217
218  def mouseDragged(event)
219    # create the image that will be dragged and
220    # a rect in which you will draw the letter in the image
221    s = @string.sizeWithAttributes(@attributes)
222    return if s.width == 0
223    an_image = NSImage.alloc.initWithSize(s)
224    image_bounds = NSRect.new([0,0],s)
225
226    # draw the letter on the image
227    an_image.lockFocus
228    drawStringCenterdIn(image_bounds)
229    an_image.unlockFocus
230
231    # get the location of the drag event
232    p = convertPoint_fromView(event.locationInWindow, nil)
233    
234    # drag from the center of the image
235    p.x = p.x  - s.width / 2
236    p.y = p.y - s.height / 2
237
238    # get the pasteboard
239    pb = NSPasteboard.pasteboardWithName(NSDragPboard)
240
241    # put the string on the pasteboard
242    writeStringToPasteboard(pb)
243
244    # start the drag
245    objc_send :dragImage, an_image,
246                     :at, p,
247                 :offset, [0,0],
248                  :event, event,
249             :pasteboard, pb,
250                 :source, self,
251              :slideBack, true
252  end
253
254  private
255
256  def log(msg)
257    $stderr.puts msg
258  end
259
260end
261