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