Cocoa Modul Serie

Kommentare anzeigen Worklog abonnieren
Gehe zu Seite Zurück  1, 2, 3, 4  Weiter

Worklogs Cocoa Modul Serie

18 - Boxenluder

Samstag, 11. Februar 2012 von d-bug
Hallo zusammen,

ich melde mich mal wieder mit einem eher langweiligem Gadget: CCBox! Kein großes Hexenwerk und auch nicht unbedingt der großen Rede wert!

BlitzMax: [AUSKLAPPEN]
SuperStrict

Import cocoa.cocoa

'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Field window:CCWindow


'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 480.0)
window = CCWindow.documentWindow(frame, CCWindowMaskTitled | CCWindowMaskClosable | CCWindowMaskMiniaturizable)
window.setDelegate(Self)
window.setTitle(AppTitle)
window.center()

frame = window.contentView().frame()

Local box:CCBox

frame.origin.x = 0.0 ; frame.origin.y = 0.0 ; frame.size.width:/3.0 ; frame.size.height:/2.0

box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Top Above")
box.setTitlePosition(CCAlignTop | CCAlignAbove)
window.contentView().addSubView(box)

frame.origin.x:+frame.size.width
box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Top")
box.setTitlePosition(CCAlignTop)
window.contentView().addSubView(box)

frame.origin.x:+frame.size.width
box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Top Below")
box.setTitlePosition(CCAlignTop | CCAlignBelow)
window.contentView().addSubView(box)

frame.origin.x = 0.0 ; frame.origin.y:+frame.size.height
box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Bottom Above")
box.setTitlePosition(CCAlignBottom | CCAlignAbove)
window.contentView().addSubView(box)

frame.origin.x:+frame.size.width
box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Bottom")
box.setTitlePosition(CCAlignBottom)
window.contentView().addSubView(box)

frame.origin.x:+frame.size.width
box = CCBox.alloc().initWithFrame(frame)
box.setTitle("Bottom Below")
box.setTitlePosition(CCAlignBottom | CCAlignBelow)
window.contentView().addSubView(box)

window.show()
End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method

End Type


user posted image
Jetzt weiß ich auch warum man kaum die Titel am unteren Rand der Box in einer Applikation sieht. Es schaut einfach doof aus und die Positionen werden auch eher seltsam interpretiert! Genau wie bei den Boxen oben links und oben rechts. Eigentlich sieht man immer nur die Box, die oben mittig dargestellt ist...


Das ist auch schon alles! Es gibt keine Notifications und keine Delegates... Eigentlich gibt es überhaupt nichts zu sehen! Geht also bitte weiter!

Grüße

17 - TextView #3 und SegmentedControl

Montag, 6. Februar 2012 von d-bug
Hallo,

heute hab ich mich mal an die letzten (hoffentlich) Reste der TextView gewagt. Jetzt kann man mittels Attributen auch Links setzen und diese via Delegate auch ausführen.

So erstellt man einen Link ein einer TextView:
BlitzMax: [AUSKLAPPEN]
		Local range:CCRange = CCMakeRange(0,4)
Local storage:CCTextStorage = textView.textStorage()

storage.beginEditing()

'set a tooltip at the first word in the text
storage.addAttribute("NSToolTipAttributeName", "Der bunte Hund", range)

'use the first word in the text as hyperlink
storage.addAttribute("NSLinkAttributeName", "http://www.blitzforum.de", range)
storage.addAttribute("NSUnderlineStyleAttributeName", CCNumber.numberWithInteger(CCUnderLineStyleSingle), range)
storage.addAttribute("NSForegroundColorAttributeName", CCColorBlue, range)
storage.endEditing()

(dies ist eine Erweiterung zum sample im Eintrag Nr. 16)

Das passende Delegate sieht in etwa so aus:
BlitzMax: [AUSKLAPPEN]
Method textViewClickedOnLink:Int(textView:CCTextView, link:Object, index:Int)
CCLog(String(link))
Return YES
End Method

Wobei hier einfach nur der Link in die Konsole geposted wird. Insgesamt gesehen ist das alles relativ umständlich, aber wenigstens funktioniert es!

Außerdem hab ich mich noch um die Integration von Kontext-Menüs gekümmert. Diese besteht nur aus einem Delegate, dass ein Menü für eine bestimmte Range im Text zurück geben kann. So ist man nicht auf ein Menü beschränkt, sondern kann für verschiedene Stellen im Text auch verschiedene Menüs zaubern.

Vorerst hab ich jetzt aber mal die Schnauze von der TextView gestrichen voll. Sie ist zwar immer noch nicht 100%ig fertig, aber immerhin kann man sie nun für Standardtextverarbeitung nutzen.



Nun zur SegmentedControl. OS X Anwender kennen ja dieses Gadget, dass im wesentlichen aus zusammen getackerten Buttons besteht (mal einfach gesagt). Natürlich ist dem nicht wirklich so, denn es ist eigentlich ein Button, der in verschiedene Segmente aufgeteilt wurde. Auf diese Segmente wird mittels Index zugegriffen.

Lange Rede kurzes Bild:
user posted image

Dazu noch das Sample:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Global completions:TList

Field window:CCWindow

'action method
Method action(sender:CCObject)
If CCSegmentedControl(sender) Notify("You've clicked Segment "+ CCSegmentedControl(sender).selectedSegment())
End Method

'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 320.0, 200.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(StripAll(AppFile))
window.center()

'get content view of the window
Local view:CCView = window.contentView()

Local segment:CCSegmentedControl
frame = view.frame()

'create default segmented control
frame.origin.x = 10.0 ; frame.origin.y = 10.0 ; frame.size.width:-20 ; frame.size.height = 22.0
segment = CCSegmentedControl.alloc().initWithFrame(frame)
segment.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
segment.setTarget(Self)
segment.setAction("action")
segment.setSegmentCount(3)
For Local i:Int = 0 Until segment.segmentCount()
segment.setTitleForSegment("Segment "+i, i)
segment.setTagForSegment(i,i)
segment.setImageForSegment(CCImage.imageNamed("NSImageNameBluetoothTemplate"),i)
Next
view.addSubView(segment)

'create segmented control with "select any" mode
frame.origin.x = 10.0 ; frame.origin.y:+(segment.frame().size.height+5.0) ; frame.size.height = 24.0
segment = CCSegmentedControl.alloc().initWithFrame(frame)
segment.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
segment.setStyle(CCSegmentedControlStyleRoundRect)
segment.setTrackingMode(CCSegmentedControlTrackingSelectAny)
segment.setTarget(Self)
segment.setAction("action")
segment.setSegmentCount(3)
For Local i:Int = 0 Until segment.segmentCount()
segment.setTitleForSegment("Segment "+i, i)
segment.setTagForSegment(i,i)
Next
segment.setEnabledForSegment(NO, 2)
view.addSubView(segment)

'create segmented control with "select any" mode
frame.origin.x = 10.0 ; frame.origin.y:+(segment.frame().size.height+5.0) ; frame.size.height = 24.0
segment = CCSegmentedControl.alloc().initWithFrame(frame)
segment.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
segment.setStyle(CCSegmentedControlStyleTexturedSquare)
segment.setTrackingMode(CCSegmentedControlTrackingMomentary)
segment.setTarget(Self)
segment.setAction("action")
segment.setSegmentCount(3)
For Local i:Int = 0 Until segment.segmentCount()
segment.setTitleForSegment("Segment "+i, i)
segment.setTagForSegment(i,i)
Next
view.addSubView(segment)

window.show()


End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method

End Type


Wie man sieht habe ich mir nicht sonderlich viel Mühe mit dem Sample gegeben, aber man kann sicherlich was daraus erkennen.


So, das war es auch schon wieder. Da ich ab morgen wieder arbeiten muss, gibt es hier wohl vor dem Wochenende keine neuen Einträge mehr.

Bis dahin...

16 - TextView #2 : es werde bunt!

Sonntag, 5. Februar 2012 von d-bug
Hallo,

heute hab ich mich den ganzen Tag mit der TextView beschäftigt. Ich wollte unbedingt Farbe ins Spiel bringen! Dazu musste noch die Klasse CCTextStorage her. Diese leitet sich von CCAttributedString ab, weswegen ich diese auch noch fertig wrappen musste. Kurzum, viel Arbeit für einen roten Hund:

user posted image

Nun ja, dafür kann man aber recht einfach einfärben. Ich finds sogar einfacher als mit MaxGUI und seinem FormatText Befehl, den keiner so richtig verstehen will. Smile

BlitzMax: [AUSKLAPPEN]
textView.textStorage().addAttribute("NSForegroundColorAttributeName", CCColorRed, CCMakeRange(0,4))

Wie man sieht, habe ich die Attributbezeichnungen original gelassen. Ich habe auch davon abgesehen die ganze Doku für die Attribute zu kopieren. Wer das nutzen will muss auf die Apple-Seite und sich die Doku da anschauen. Es gibt derer einfach zu viele!


Die Completion-List ist auch wieder implementiert! (siehe dazu den Eintrag 11 - Spaß mit Textfeldern #01)


Außerdem kann die Textview jetzt auch tooltips anzeigen, die allerdings auch mit Attributen gesetzt werden muss:
BlitzMax: [AUSKLAPPEN]
textView.textStorage().addAttribute("NSToolTipAttributeName", "Der bunte Hund", CCMakeRange(0,4))

user posted image


So! Nebenbei habe ich noch die CCColor Klasse an die NSColor Klasse gebunden. Diese war vorher eine eigenständige Klasse und brauchte diverse Daten-Schaufel-Funktionen auf beiden Seiten. Irgendwie war ich da wohl nicht ganz bei mir, als ich diesen Scheiß gebaut habe. Gleiches gilt übrigens auch für die CCNumber Klasse.


Das war also mein Sonntag.

Bis dahin!

15 - Kleiner Randgruppen Tertz

Samstag, 4. Februar 2012 von d-bug
Hallo zusammen,

um in der TextView weiter zu kommen, brauche ich erst mal die fertige CCAttributedString Klasse. Um diese aber fertig zu machen, benötige ich zuerst die CCDictionary Klasse. Diese habe ich jetzt erst mal komplettiert.

Die CCDictionary Klasse ist im Prinzip nichts anderes als die brl.TMap Klasse. Tatsächlich ist sie nur ein Erbe der TMap mit ein paar Goodies. Zum einen kann man sie direkt in eine "plist" schreiben bzw. lesen, zum anderen kann man sie mit einem NSMutableDictionary synchronisieren. Um die Wahrheit zu sagen ist das im Moment aber auf ein paar Datentypen beschränkt: CCNumber, CCColor, CCRect, CCSize, CCPoint, CCRange, CCDictionary und String! Wahrscheinlich werden noch ein paar folgen, aber im Moment benötige ich sie einfach nicht.

Jetzt erst mal das unkommentierte Sample:
BlitzMax: [AUSKLAPPEN]
Framework cocoa.core

Local dict:CCDictionary = CCDictionary.alloc().init()

dict.setValueForKey("Ein String", "CCStringKey")
dict.setValueForKey(CCNumber.numberWithBool(YES), "CCBoolKey")
dict.setValueForKey(CCNumber.numberWithInteger(4321), "CCIntegerKey")
dict.setValueForKey(CCNumber.numberWithFloat(4.321), "CCFloatKey")
dict.setValueForKey(CCNumber.numberWithDouble(1.234), "CCDoubleKey")
dict.setValueForKey(CCMakeRange(1, 2000), "CCRangeKey")
dict.setValueForKey(CCMakeRect(0,0,100,100), "CCRectKey")
dict.setValueForKey(CCMakeSize(100,100), "CCSizeKey")
dict.setValueForKey(CCMakePoint(0,0), "CCPointKey")

Local dict2:CCDictionary = CCDictionary.alloc().init()
dict2.setValueForKey(CCColorRed,"Red")
dict2.setValueForKey(CCColorGreen, "Green")
dict2.setValueForKey(CCColorBlue, "Blue")
dict.setValueForKey(dict2, "CCDictionaryKey")

CCLog(dict)

CCLog(dict.numberForKey("CCBoolKey"))


dict.write("test.plist")
dict = CCDictionary.open("test.plist")

Local key:String
Local value:CCRect

key = "CCRectKey"
value = dict.rectForKey(key)
If Not value
CCLog("No value found for key: "+key)
Else
CCLog(value)
EndIf


...danach das Ergebnis aus der Konsole:
Code: [AUSKLAPPEN]
Building ccdictionary_sample
Compiling:ccdictionary_sample.bmx
Linking:ccdictionary_sample.debug
Executing:ccdictionary_sample.debug

cocoa.cocoa @ application: BlitzMax Application / runtime: 3ms
  class  : CCDictionary
  values : key : CCBoolKey / value class : CCNumber
           key : CCDictionaryKey / value class : CCDictionary
           key : CCDoubleKey / value class : CCNumber
           key : CCFloatKey / value class : CCNumber
           key : CCIntegerKey / value class : CCNumber
           key : CCPointKey / value class : CCPoint
           key : CCRangeKey / value class : CCRange
           key : CCRectKey / value class : CCRect
           key : CCSizeKey / value class : CCSize
           key : CCStringKey / value class : String
           

cocoa.cocoa @ application: BlitzMax Application / runtime: 7ms
  class  : CCNumber
  type   : Bool
  value  : YES
  string : {1,0}

cocoa.cocoa @ application: BlitzMax Application / runtime: 8ms
  class  : CCRect
  origin : 0.00000000,0.00000000
  size   : 100.000000x100.000000
  string : {{0.00000000,0.00000000}, {100.000000,100.000000}}

Process complete




...und als letztes die geschriebene plist im XCode-PListViewer:
user posted image
(Seit wann werden Bools eigentlich nicht mehr als CheckBox angezeigt?)

Dem geübten Auge ist aufgefallen, dass Floats auch als Double gespeichert werden. Das ist leider so. Schreibt man das ganze in eine pList, werden Floats in NSNumber konvertiert und holt man es wieder von der Platte, weiß Cocoa leider nicht mehr was in der NSNumber hinterlegt wurde. Man muss eben selber casten.



Ob man es nun glaubt oder nicht, so etwas hält einen extrem auf. Diese ganzen kleinen Kleinigkeiten, die man noch implementieren muss, um eine bestimmte Klasse komplettieren zu können, nerven schon ein wenig. Aber was tut man nicht alles fürs Endergebnis.

Auf jeden Fall ist das nun das Werk des Tages, denn im Moment hab ich erst mal keine Lust mehr. Morgen geht's dann wieder ans Werk!


Grüße!

14 - TextView die Erste

Sonntag, 29. Januar 2012 von d-bug
Hallo zusammen,

heute Morgen habe ich damit begonnen die TextView Klasse zu wrappen. Da diese aber aus gefühlten 2000 Methoden besteht (NSText mal mit eingerechnet, auf der NSTextView basiert), gestaltet sich das alles als recht müßig. Momentan bin ich soweit, dass alle Methoden, die ich ohne großen Aufstand wrappen konnte auch schon gewrappt habe.

In der TextView kommt auch zum ersten mal NSRange vermehrt vor. Will heißen, ich musste mir noch ein Struct implementieren, dass ich zwischen BlitzMax und Objective-C hin und her schieben kann. Das hat auch noch ein paar Minütchen in Anspruch genommen. Musste ja schließlich Funktionen zum kopieren der Daten (Fields), neue OBJC_sendMessage Funktionen für getter und setter und Datenkonvertierungsfunktionen schreiben. Wie auch immer, CCRange ist jetzt so weit implementiert, dass man damit schon arbeiten kann. Alles weitere folgt erst bei bedarf.

Aber zurück zur TextView... Momentan gibt es noch ca. 30 bis 40 Methoden zu implementieren, die aber alle irgend welche Erweiterungen des cocoa.cocoa Moduls zur Folge haben. Dazu habe ich heute nun wirklich keine Lust mehr. Die ganzen Delegate-Methoden und Notifications sind auch noch nicht implementiert... Arbeit über Arbeit...

Man kann allerdings schon was sehen, bzw. auch was schreiben! Dazu gibt es wahrscheinlich im nächsten Worklog-Eintrag etwas mehr Beispiel und Screen zu sehen.

Ein wenig Beispielcode:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Field window:CCWindow
Field textView:CCTextView



Method selectAction(sender:CCObject)
CClog(textView.selectedRange())
End Method



'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 200.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(StripAll(AppFile))
window.center()

'get content view of the window
Local view:CCView = window.contentView()

Local scrollView:CCScrollView
frame = view.frame()

scrollView = CCScrollView.alloc().initWithFrame(frame)
scrollView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)
scrollView.setDelegate(Self)
window.setContentView(scrollView)

textView = CCTextView.alloc().initWithFrame(frame)
scrollView.setDocumentView(textView)
textView.setDelegate(Self)
textView.insertText("Hund Katze Maus Pferd Elefant")




app.applicationMenu().insertItemWithTitle(CCLocalizedString("About {AppTitle}"), "selectAction", "", Self, 0)

window.show()

End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method


End Type


...und ein nichts sagender Screen:
user posted image


So ganz am Rande gabs auch noch die CCStepper Klasse, die ich gestern Abend noch implementierte. Dazu gibt es aber kein Beispiel oder Screen! Ein Stepper ist ein Stepper und das implementieren war auch eher langweilig. Es handelte sich ja schließlich um eine Erweiterung der CCControl Klasse und war nach 5 / 6 Methoden auch schon gegessen!

Schönes Rest-Wochenende noch!

13 - Progress-und Levelindicator und Slider

Samstag, 21. Januar 2012 von d-bug
Hallo,

hab wohl gerade eindeutig eine hoch motivierte Phase, die ich dazu nutze lauter Kleinkram zu machen. Heute entstanden daraus dann CCProgressIndicator, CCLevelIndicator und CCSlider. Da ich wirklich nicht einsehe jedes Gadget ausführlich zu erklären, gibt ab jetzt einfach nur noch ein Sample nebst Screenshot bei standard Zeugs. Natürlich auch mit ein wenig Begleittext, dass gebietet mir schon die Höflichkeit. Auch wenn manche meinen ich sei unhöflich... Ich bin gar nicht so schlimm! Wink

Extra lange Sample code:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Global completions:TList

Field window:CCWindow


Method sliderAction(sender:CCObject)
If CCSlider(sender) CCLog(String(CCSlider(sender).doubleValue()))
End Method



'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 330.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(StripAll(AppFile))
window.center()

'get content view of the window
Local view:CCView = window.contentView()

Local progress:CCProgressIndicator
frame = view.frame()

'indeterminate progress indicator
frame.origin.x = 10.0 ; frame.origin.y = 10.0 ; frame.size.width:-20.0
frame.size.height = CCProgressIndicatorThicknessDefault
progress = (New CCProgressIndicator).initWithFrame(frame)
progress.setIndeterminate(YES)
progress.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
progress.startAnimation()
progress.sizeToFit()
view.addSubView(progress)

'progress indicator with small size
frame = progress.frame()
frame.origin.y:+(frame.size.height+5.0)
progress = (New CCProgressIndicator).initWithFrame(frame)
progress.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
progress.setControlSize(CCControlSizeSmall)
progress.setMinValue(0.0)
progress.setMaxValue(100.0)
progress.setDoubleValue(75.0)
progress.startAnimation()
progress.sizeToFit()
view.addSubView(progress)

'indeterminate circular progress indicator
frame = progress.frame()
frame.size.height = CCProgressIndicatorThicknessDefault
frame.size.width = CCProgressIndicatorThicknessDefault
frame.origin.y:+(frame.size.height+5.0)
progress = (New CCProgressIndicator).initWithFrame(frame)
progress.setIndeterminate(YES)
progress.setLayout(CCAlignTop | CCAlignLeft)
progress.setStyle(CCProgressIndicatorStyleCircular)
progress.startAnimation()
progress.sizeToFit()
view.addSubView(progress)

'circular progress indicator (is not animated)
frame = progress.frame()
frame.size.height = CCProgressIndicatorThicknessDefault
frame.size.width = CCProgressIndicatorThicknessDefault
frame.origin.x:+40.0
progress = (New CCProgressIndicator).initWithFrame(frame)
progress.setLayout(CCAlignTop | CCAlignLeft)
progress.setStyle(CCProgressIndicatorStyleCircular)
progress.setMinValue(0.0)
progress.setMaxValue(60.0)
progress.setDoubleValue(20.0)
progress.sizeToFit()
view.addSubView(progress)

'level indicator with warning and critical values (discrete style)
Local indicator:CCLevelIndicator
frame.origin.x = 10.0 ; frame.origin.y:+(progress.frame().size.height+5.0)
frame.size.width = view.frame().size.width - 20.0 ; frame.size.height = 22.0
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleDiscrete)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(50.0)
indicator.setCriticalValue(40.0)
indicator.setWarningValue(35.0)
indicator.setDoubleValue(30.0)
view.addSubView(indicator)

frame.origin.y:+(frame.size.height+5.0)
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleDiscrete)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(50.0)
indicator.setCriticalValue(40.0)
indicator.setWarningValue(35.0)
indicator.setDoubleValue(35.0)
view.addSubView(indicator)

frame.origin.y:+(frame.size.height+5.0)
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleDiscrete)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(50.0)
indicator.setCriticalValue(40.0)
indicator.setWarningValue(35.0)
indicator.setDoubleValue(40.0)
view.addSubView(indicator)

'level indicator with tick marks (continuous style)
frame.origin.y:+(frame.size.height+5.0)
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleContinuous)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(50.0)
indicator.setDoubleValue(35.0)
indicator.setNumberOfTickMarks(11)
indicator.setNumberOfMajorTickMarks(3)
view.addSubView(indicator)

'level indicator (relevancy style)
frame.origin.y:+(frame.size.height+5.0)
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleRelevancy)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(30.0)
indicator.setDoubleValue(30.0)
view.addSubView(indicator)

'level indicator (rating style)
frame.origin.y:+(frame.size.height+5.0)
indicator = (New CCLevelIndicator).initWithFrame(frame)
indicator.setStyle(CCLevelIndicatorStyleRating)
indicator.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
indicator.setMinValue(0.0)
indicator.setMaxValue(5.0)
indicator.setDoubleValue(5.0)
view.addSubView(indicator)

'slider allowing only tick mark values
Local slider:CCSlider
frame.origin.y:+(frame.size.height+5.0)
slider = (New CCSlider).initWithFrame(frame)
slider.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
slider.setMinValue(0.0)
slider.setMaxValue(100.0)
slider.setDoubleValue(50.0)
slider.setNumberOfTickMarks(11)
slider.setAllowsTickMarkValuesOnly(YES)
slider.setTarget(Self)
slider.setAction("sliderAction")
view.addSubView(slider)

'slider
frame.origin.y:+(frame.size.height+5.0)
slider = (New CCSlider).initWithFrame(frame)
slider.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
slider.setMinValue(0.0)
slider.setMaxValue(100.0)
slider.setDoubleValue(50.0)
slider.setTarget(Self)
slider.setAction("sliderAction")
view.addSubView(slider)

'circular slider allowing only tick mark values
frame.origin.y:+(frame.size.height+5.0)
frame.size.width = 32.0 ; frame.size.height = 32.0
slider = (New CCSlider).initWithFrame(frame)
slider.setLayout(CCAlignTop | CCAlignLeft)
slider.setStyle(CCSliderStyleCircular)
slider.setMinValue(0.0)
slider.setMaxValue(60.0)
slider.setDoubleValue(15.0)
slider.setNumberOfTickMarks(12)
slider.setAllowsTickMarkValuesOnly(YES)
slider.setTarget(Self)
slider.setAction("sliderAction")
view.addSubView(slider)

'circular slider allowing only tick mark values
frame.origin.x:+(frame.size.width+5.0)
frame.size.width = 32.0 ; frame.size.height = 32.0
slider = (New CCSlider).initWithFrame(frame)
slider.setLayout(CCAlignTop | CCAlignLeft)
slider.setStyle(CCSliderStyleCircular)
slider.setMinValue(0.0)
slider.setMaxValue(60.0)
slider.setDoubleValue(20.0)
slider.setTarget(Self)
slider.setAction("sliderAction")
view.addSubView(slider)

window.show()

End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method

End Type


...passendes Bild dazu:
user posted image



Ich glaube ich hab nun für heute genug Code produziert und begebe mich jetzt mal nach Himmelsrand! Da erwarten mich ganz andere Herausforderungen!

Grüße

12 - Von Tabs, Screen und PopupButtons

Freitag, 20. Januar 2012 von d-bug
Und weiter gehts:

CCScreen
Hier bedarf es keines Screenshots! Im wesentlichen ist es eine Klasse, die einem die aktuellen Desktop-Auflösungen zurück gibt. Dazu gibt es die Funktion CCScreen.screens() die einem die Liste aller Screens zurück gibt. Mit screen.frame() bekommt man die gesamt Größe des Screens und mit screen.visibleFrame() die Größe des Screens abzüglich der Menü-Zeile oben und des Docks unten.

Hierbei ist nur zu sagen, dass das Cocoa Koordinaten-System unten/links beginnt, nicht wie bei BlitzMax üblich oben/links.

BlitzMax: [AUSKLAPPEN]
CCLog(CCScreen.deepestScreen().frame())
CCLog(CCScreen.deepestScreen().visibleFrame())


Ergebnis aus der Konsole:
Code: [AUSKLAPPEN]
cocoa.cocoa @ application: CCApplication-Sample.debug / runtime: 41ms
  class  : CCRect
  origin : 0.00000000,0.00000000
  size   : 2560.00000x1440.00000
  string : {{0.00000000,0.00000000}, {2560.00000,1440.00000}}

cocoa.cocoa @ application: CCApplication-Sample.debug / runtime: 41ms
  class  : CCRect
  origin : 0.00000000,64.0000000
  size   : 2560.00000x1354.00000
  string : {{0.00000000,64.0000000}, {2560.00000,1354.00000}}


Oben die komplette Auflösung und unten die Auflösung abzüglich Menubar und Dock!




CCTabView und CCTabViewItem
Auch nichts wirklich dramatisches, aber immerhin mit Screen und Sample:
user posted image
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Field window:CCWindow

'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 200.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(StripAll(AppFile))
window.center()

'get content view of the window
Local view:CCView = window.contentView()

Local tabview:CCTabView
frame = view.frame()

tabView = (New CCTabView).initWithFrame(frame)
tabView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)
tabView.setDelegate(Self)
window.setContentView(tabView)

Local item:CCTabViewItem
item = (New CCTabViewItem).initWithIdentifier(Null)
item.setContentView((New CCView).initWithFrame(tabView.contentRect()))
item.setTitle("Hund")
tabView.addItem(item)

item = (New CCTabViewItem).initWithIdentifier(Null)
item.setContentView((New CCView).initWithFrame(tabView.contentRect()))
item.contentView().setBackgroundColor(CCColorRed)
item.setTitle("Katze")
tabView.addItem(item)

item = (New CCTabViewItem).initWithIdentifier(Null)
item.setContentView((New CCView).initWithFrame(tabView.contentRect()))
item.contentView().setBackgroundColor(CCColorGreen)
item.setTitle("Maus")
tabView.addItem(item)

item = (New CCTabViewItem).initWithIdentifier(Null)
item.setContentView((New CCView).initWithFrame(tabView.contentRect()))
item.contentView().setBackgroundColor(CCColorBlue)
item.setTitle("Pferd")
tabView.insertItem(item, 1)
tabView.selectItem(item)

window.show()

End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method


Method tabViewDidSelectTabViewItem(tabView:CCTabView, tabViewItem:CCTabViewItem)
CCLog("tab view did select item : "+tabViewItem.title())
End Method

Method tabViewShouldSelectTabViewItem:Int(tabView:CCTabView, tabViewItem:CCTabViewItem)
CCLog("tab view should select item : "+tabViewItem.title())
Return YES
End Method

Method tabViewWillSelectTabViewItem(tabView:CCTabView, tabViewItem:CCTabViewItem)
CCLog("tab view will select item : "+tabViewItem.title())
End Method

Method tabViewDidChangeNumberOfTabViewItems(tabView:CCTabView)
CCLog("tab view did change number of items to: "+tabview.numberOfItems())
End Method



End Type





CCPopUpButton und CCPullDownButton
Da ich hier das CCButton-Sample erweitert habe, gibts nur einen kleinen Ausschnitt aus dem Code:
BlitzMax: [AUSKLAPPEN]
...
'initilaize popup-button
frame = colorWell.frame() ; frame.origin.y:+(frame.size.height+2.0)
Local popUpButton:CCPopUpButton = (New CCPopUpButton).initWithFrame(frame)
popUpButton.addItemsWithTitles(["Hund","Katze","Maus","Pferd","Elefant"])
popUpButton.setDelegate(Self)
popUpButton.setTarget(Self)
popUpButton.setAction("action")
view.addSubView(popUpButton)

'initilaize popup-button
frame = popUpButton.frame() ; frame.origin.y:+(frame.size.height+2.0)
Local pullDownButton:CCPullDownButton = (New CCPullDownButton).initWithFrame(frame)
pullDownButton.addItemsWithTitles(["Hund","Katze","Maus","Pferd","Elefant"])
view.addSubView(pullDownButton)
...

Und natürlich das Bild dazu:
user posted image



Da ich es gerade recht eilig habe, ist dieser Eintrag eher kurz und bündig geraten.

Grüße!

11 - Spaß mit Textfeldern #01

Mittwoch, 18. Januar 2012 von d-bug
Hallo zusammen,

da ich meinen Urlaub nun erfolgreich hinter mich gebracht habe, mach ich hier mal munter weiter!

Eigentlich hatte ich geplant mir die NSTextView vorzunehmen, bin aber erst mal an den kleinen Geschwistern NSTextField, NSSecureTextField und NSSearchField hängen geblieben.

Mit erstaunen habe ich feststellen müssen, dass es eine Completion-Integration gibt, wenn man hinter einem angefangenem Wort ESC drückt. Irgendwie ist mir das vorher nie aufgefallen. Die Liste der Wörter wird normalerweise aus der Datenbank der Lexikon.app gezogen, lässt sich aber ziemlich einfach manipulieren (siehe Sample). Da mir das nie aufgefallen ist nun meine Frage: Ist das erst seit Lion so, oder war das vorher auch schon?
Die große Recherche mittels Google brachte mich da auch nicht weiter. Die Funktionalität als solche ist wohl schon seit OSX 10.3 integriert, aber dass es in jedem Textfeld standardmäßig per ESC aufgerufen werden kann ist mir neu. Selbst die MaxIDE macht das jetzt und da ist mir das auch nicht aufgefallen, obwohl ich sie ja nun verdammt oft bediene...

Wie auch immer... Sample:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Global completions:TList

Field window:CCWindow

'action method
Method action(sender:CCObject)
If CCTextField(sender) Notify("You've clicked Enter.~nText field text: '"+CCTextField(sender).title()+"'")
End Method

'action method
Method search(sender:CCObject)
If CCSearchField(sender) CCLog("search term: "+CCSearchField(sender).title())
End Method

Method changeColor(sender:CCObject)
Local well:CCColorWell = CCColorWell(sender)
If Not well Return
window.contentView().setBackgroundColor(well.color())
End Method


'use this method to initialize gadgets
Method CCApplicationDidFinishLaunchingNotification(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 200.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(StripAll(AppFile))
window.center()

'get content view of the window
Local view:CCView = window.contentView()

Local textField:CCTextField
frame = view.frame()

'create a simple text field
frame.origin.x = 10.0 ; frame.origin.y = 10.0 ; frame.size.width:-20 ; frame.size.height = 22.0
textField = (New CCTextField).initWithFrame(frame)
textField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
textField.setPlaceholderString("Type your text here (hit ESC for completion list and ENTER for action)")
textField.setDelegate(Self)
textField.setAction("action")
textField.setTarget(Self)
view.addSubView(textField)

'create a label
frame.origin.y:+(frame.size.height+5.0)
textField = CCTextField.labelWithFrame(frame)
textField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
textField.setTitle("Label not selectable")
view.addSubView(textField)

'create a selectable label
frame.origin.y:+(frame.size.height+5.0)
textField = CCTextField.labelWithFrame(frame)
textField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
textField.setTitle("Label selectable")
textfield.setSelectable(YES)
view.addSubView(textField)

'create a secure text field
frame.origin.y:+(frame.size.height+5.0)
textField = (New CCSecureTextField).initWithFrame(frame)
textField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
textField.setTitle("Passwort")
textField.setDelegate(Self)
textField.setAction("action")
textField.setTarget(Self)
view.addSubView(textField)

'create a search field with recents-menu and custom recents-terms
Local searchField:CCSearchField
frame.origin.y:+(frame.size.height+5.0)
searchField = (New CCSearchField).initWithFrame(frame)
searchField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
searchField.setPlaceholderString("Type your search terms here")
searchField.setDelegate(Self)
searchField.setAction("search")
searchField.setTarget(Self)
view.addSubView(searchField)

'create recents-menu template
Local menu:CCMenu = CCMenu.menu()
Local item:CCMenuItem
item = menu.addItemWithTitle("Clear",CCNullAction,"",CCNullTarget)
item.setTag(CCSearchFieldClearRecentsMenuItemTag)
menu.addItem(CCMenuItem.separatorItem())
item = menu.addItemWithTitle("Recent Searches",CCNullAction,"",CCNullTarget)
item.setTag(CCSearchFieldRecentsTitleMenuItemTag)
item = menu.addItemWithTitle("Recents",CCNullAction,"",CCNullTarget)
item.setTag(CCSearchFieldRecentsMenuItemTag)
searchField.setSearchMenuTemplate(menu)

'delete menu! it is just a template in isn't needed after setting it to the search field
menu = Null


'create the global completions list
completions = New TList
completions.addLast("Hund")
completions.addLast("Katze")
completions.addLast("Maus")
completions.addLast("Pferd")
completions.addLast("Elefant")

window.show()


End Method

'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method

'log input if text field isn't a search field
Method CCControlTextDidChangeNotification(notification:CCNotification)
If Not CCSearchField(notification.obj) CCLog(notification)
End Method

'manipulate the list of suggestions for completion behavior
'this is limited to CCTextField class
'return Null to surpress the completions list
Method textFieldCompletionsForPartialWord:TList(textField:CCTextField, partialWord:String, suggestions:TList)
Return completions
End Method

End Type


Ein Bild dazu:
user posted image
Hier noch ohne "Elefant"



Das war es auch schon wieder!

Grüße

10 - Letzte Worte...

Donnerstag, 5. Januar 2012 von d-bug
...vorm Urlaub!

Da ich nun meinen verdienten Urlaub antreten werde, poste ich noch kurz die letzten Änderungen!

Hinzugekommen sind das ColorWell und das ColorPanel. Ersteres ist eine Art Button zum öffnen des ColorPanels. Die Farbe wird hier live geändert, so dass man auf dem ColorWell immer die aktuelle Farbe angezeigt bekommt. Das ColorPanel selbst sollte eigentlich klar sein.

Da ich das Button-Sample um das ColorWell erweitert habe, hier nur ein Ausschnitt des Aufrufs:
BlitzMax: [AUSKLAPPEN]
		'initialize colorWell
frame = button.frame() ; frame.origin.y:+(frame.size.height+2.0)
Local colorWell:CCColorWell = (New CCColorWell).initWithFrame(frame)
colorWell.SetColor(CCColorRed)
view.addSubview(colorWell)

'initialize colorPanel
CCColorPanel.sharedColorPanel().setDelegate(Self)
CCColorPanel.sharedColorPanel().setTarget(window.contentView())
CCColorPanel.sharedColorPanel().setAction("setBackgroundColor")
CCColorPanel.sharedColorPanel().setShowsAlpha(YES)


Außerdem gibt's noch ein hässlichen gelben Screen:
user posted image

Warum das ColorWell gelb ist hab ich ja bereits oben erklärt. Der Hintergrund ist aber ebenfalls gelb?!
Ja, das liegt daran, dass ich die Notification und die Delegate Methoden des ColorPanels auf die Haupt-View (content view) des Fensters angewendet habe. Diese bekommt also auch live ihre Farbe geändert wenn man im ColorPanel die Farbe ändert.

Da im System nur ein ColorPanel zulässig ist, müssen Target und Action also immer dann gesetzt werden, wenn man auf eine andere Methode zugreifen will. Delegate als solches MUSS auch gesetzt werden, wenn man auf diese Funktionalität zugreifen möchte, ansonsten werden die Notifications und Delegates gar nicht erst ausgelöst.



Außerdem hatte ich die Schnauze davon voll, ständig die Notifications aus der Apple Dokumentation formatieren zu müssen, also heißen die aufgerufenen Methoden jetzt wie die Namen der Notification, außer das man NS gegen CC austauschen muss. Ein Bseispiel:

aus Apples Dokumentation:
BlitzMax: [AUSKLAPPEN]
NSColorPanelColorDidChangeNotification


früher im cocoa.cocoa Modul:
BlitzMax: [AUSKLAPPEN]
Method colorPanelColorDidChange(notification:CCNotification)


aktuell aus cocoa.cocoa:
BlitzMax: [AUSKLAPPEN]
Method CCColorPanelColorDidChangeNotification(notification:CCNotification)


So viel zu Randinformationen!


Ich bin also jetzt bis zum 16.01. in Urlaub! Neuigkeiten wird's also erst mal keine geben!

Pfürti!


~edit 18:02~
Anmerkung der Redaktion:
Das Ding heißt wirklich ColorWell und nicht ColorWheel...

09 - OutlineView

Samstag, 31. Dezember 2011 von d-bug
Hallo zusammen,

so quasi zum Jahresabschluss gibt es nun die CCOutlineView Klasse. Diese ist, einfach gesprochen, eine Struktur-Baum Ansicht der CCTableView-Klasse. Kurzum die TreeView!

Viel zu sagen gibt's dazu nicht. Jeder kennt sie und jeder nutzt sie, sofern er denn MaxGUI oder dergleichen hat.
Im Aufbau gleicht sie der Table-View von letztens, wenn auch ein paar Methoden dazu kamen.

Sample:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa


'create global CCSampleController instance
Global controller:CCSampleController = New CCSampleController

'create global CCApplication instance
Global app:CCApplication = (New CCApplication).init()

'bind controller as delegate to the application
app.setDelegate(controller)

'start the applications main loop
app.run()


'Controller class
Type CCSampleController Extends CCObject

Field window:CCWindow

Field columnA:CCTableViewColumn
Field columnB:CCTableViewColumn

'use this method to initialize gadgets
Method applicationDidFinishLaunching(notification:CCNotification)

'create window
Local frame:CCRect = CCMakeRect(100.0, 100.0, 640.0, 480.0)
window = CCWindow.documentWindow(frame)
window.setDelegate(Self)
window.setTitle(AppTitle)
window.center()

Local scrollView:CCScrollView = CCScrollView.scrollView(window.contentView().frame())
scrollView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)
scrollView.setDelegate(Self)
window.contentView().addSubView(scrollView)

Local outlineView:CCOutlineView = (New CCOutlineView).initWithFrame(CCMakeRect(0,0,800,600))
scrollView.setDocumentView(outlineView)
outlineView.setDelegate(Self)
'outlineView.setSelectionHighlightStyle(CCTableViewSelectionHighlightStyleSourceList)
outlineView.setAutoresizesOutlineColumn(YES)

columnA = outlineView.addColumnWithTitle("Tree")
outlineView.setOutlineTableColumn(columnA)

columnB = outlineView.addColumnWithTitle("Comment")

For Local i:Int = 0 Until 10
outlineView.addNode((New CCSampleGroupNode).initWithTitle("Group Node "+i, "Some group node text"))
Next

outlineView.sizeLastColumnToFit()
outlineView.reloadData()

window.show()
End Method

Method outlineViewColumnDidMove(notification:CCNotification)
CCLog(notification)
End Method

Method outlineViewItemDidCollapse(notification:CCNotification)
CCLog(notification)
End Method

Method outlineViewItemDidExpand(notification:CCNotification)
CCLog(notification)
End Method


'terminate application when last window is closed
Method applicationShouldTerminateAfterLastWindowClosed:Int()
Return YES
End Method

End Type





Type CCSampleNode Extends CCTableViewNode

Field _title:String
Field _value:String

Method initWithTitle:CCSampleNode(title:String, value:String)
_title = title
_value = value
Return Self
End Method

'return value must be of type String or CCObject
'this method is abtract
Method dataForColumn:Object(column:CCTableViewColumn)
Select column
Case controller.columnA ; Return _title
Case controller.columnB ; Return _value
End Select
End Method

'allow editing of rows when column is editable and the rows aren't group rows
Method isEditable:Int(column:CCTableViewColumn)
Return YES
End Method

Method isGroupNode:Int()
Return NO
End Method

Method setDataForColumn(data:Object, column:CCTableViewColumn)
Select column
Case controller.columnA
If String(data)
_title = String(data)
EndIf
Case controller.columnB
If String(data)
_value = String(data)
EndIf
End Select
End Method

End Type

Type CCSampleGroupNode Extends CCSampleNode

Method initWithTitle:CCSampleNode(title:String, value:String)
_title = title
_value = value

For Local i:Int = 0 Until 10
addNode((New CCSampleNode).initWithTitle("Sub node "+i, "some text "+i))
Next

Return Self
End Method

Method isEditable:Int(column:CCTableViewColumn)
Return YES
End Method

Method isGroupNode:Int()
Return NO
End Method

End Type



Bild:
user posted image


Kleiner Aufruf an Apple:
Liebes Volk von Apple, wäre es nicht einfacher gewesen sowohl die Delegate Methoden der Table-View als auch die Delegate-Methoden der Outline-View mit dem Datasource als Parameter zu versehen? Bei der Outline-View habt ihrs doch gemacht! Es wäre so toll, wenn beide Views auf nur einen Satz Methoden zurückgreifen könnten. Es hat bestimmt auch Nachteile in Form von Überschneidungen oder dergleichen, aber dafür könnte man ja einfach einen zweiten Controller nutzen! Aber so wie es jetzt ist, ist es einfach irgendwie unnötig kompliziert!

Musste ich einfach mal los werden. Ich werde btw. genau dieses jetzt noch machen. Table-View und Outline-View Delegates und Notifications in einen Namespace zusammen packen. Ist ja eh kein 1:1 Rip der Cocoa Library.

Grüße.

Gehe zu Seite Zurück  1, 2, 3, 4  Weiter