Cocoa Modul Serie

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

Worklogs Cocoa Modul Serie

28 - OpenGL

Sonntag, 18. März 2012 von d-bug
Hallo zusammen,

da ich in den Kommentaren ja mal auf einen Max2D Treiber, bzw. einer OpenGLView angesprochen wurde, habe ich mich jetzt mal darauf gestürzt. Bisher handelt es sich dabei um eine 1:1 Umsetzung der NSOpenGLView, die von Hause aus bereits den OpenGL Kontext bereit stellt. Die ganze OpenGLView lebt vom subclassing. Ohne dem kann sie weder etwas darstellen noch sonst irgend etwas machen.

Da ich heute morgen erst damit anfing, kann ich eigentlich schon recht stolz darauf sein, dass es mir bereits gelungen ist das NEHE 5 Tutorial darzustellen. Bisher allerdings noch ohne Animation, da mir die NSTimer Klasse noch fehlt um das Neuzeichnen auszulösen! Man kann es wohl simulieren, in dem man das Fenster vergrößert bzw. verkleinert um den Neuaufbau zu erzwingen, aber das ist mir zu müßig.



Kleiner Code:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.cocoa
Import pub.opengl

'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)
window.setDelegate(Self)
window.setTitle(AppTitle)
window.center()

'create the OpenGL view.
window.setContentView(CCOpenGL.alloc().initWithFrame(window.contentView().frame()))
window.show()

End Method

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

End Type

'Subclass of CCOpenGLView
Type CCOpenGL Extends CCOpenGLView

Function alloc:CCOpenGL()
Return New CCOpenGL
End Function

Method initWithFrame:CCOpenGL(frame:CCRect)

'Create Max2D default pixel format
Local pixelFormatAttributes:Int[] = [CCOpenGLDoubleBuffer, CCOpenGLDepthSize, 1, CCOpenGLNoRecovery]
Local pixelFormat:CCOpenGLPixelFormat = CCOpenGLPixelFormat.alloc().initWithAttributes(pixelFormatAttributes)

'initialize the view and attach the pixelformat to it
Super.initWithFramePixelFormat(frame, pixelFormat)
setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)

Return Self
End Method

'draw nehe 5 tutorial to the view
Method DrawRect(rect:CCRect)
Global rtri:Float=0.0
Global rquad:Float=0.0
glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
glLoadIdentity
glTranslatef -1.5,0.0,-6.0
glRotatef rtri,0.0,1.0,0.0 '; Rotate The Triangle On The Y axis ( New )
glBegin GL_POLYGON
';Front
glColor3f 1.0,0.0,0.0 '; Red
glVertex3f 0.0, 1.0, 0.0 '; Top Of Triangle (Front)
glColor3f 0.0,1.0,0.0 '; Green
glVertex3f -1.0,-1.0, 1.0 '; Left Of Triangle (Front)
glColor3f 0.0,0.0,1.0 '; Blue
glVertex3f 1.0,-1.0, 1.0 '; Right Of Triangle (Front)
';Right
glColor3f 1.0,0.0,0.0 '; Red
glVertex3f 0.0, 1.0, 0.0 '; Top Of Triangle (Right)
glColor3f 0.0,0.0,1.0 '; Blue
glVertex3f 1.0,-1.0, 1.0 '; Left Of Triangle (Right)
glColor3f 0.0,1.0,0.0 '; Green
glVertex3f 1.0,-1.0, -1.0 '; Right Of Triangle (Right)
';Back
glColor3f 1.0,0.0,0.0 '; Red
glVertex3f 0.0, 1.0, 0.0 '; Top Of Triangle (Back)
glColor3f 0.0,1.0,0.0 '; Green
glVertex3f 1.0,-1.0, -1.0 '; Left Of Triangle (Back)
glColor3f 0.0,0.0,1.0 '; Blue
glVertex3f -1.0,-1.0, -1.0 '; Right Of Triangle (Back)
';Left
glColor3f 1.0,0.0,0.0 '; Red
glVertex3f 0.0, 1.0, 0.0 '; Top Of Triangle (Left)
glColor3f 0.0,0.0,1.0 '; Blue
glVertex3f -1.0,-1.0,-1.0 '; Left Of Triangle (Left)
glColor3f 0.0,1.0,0.0 '; Green
glVertex3f -1.0,-1.0, 1.0 '; Right Of Triangle (Left)
glEnd

glLoadIdentity
glTranslatef 1.5,0.0,-7.0 '; Move Right 1.5 Units And Into The Screen 1
glRotatef rquad,1.0,1.0,1.0 '; Rotate The Quad On The X axis ( New )
glColor3f 0.5,0.5,1.0 '; Set The Color To Blue One Time Only
glBegin GL_QUADS
glColor3f 0.0,1.0,0.0 '; Set The Color To Blue
glVertex3f 1.0, 1.0,-1.0 '; Top Right Of The Quad (Top)
glVertex3f -1.0, 1.0,-1.0 '; Top Left Of The Quad (Top)
glVertex3f -1.0, 1.0, 1.0 '; Bottom Left Of The Quad (Top)
glVertex3f 1.0, 1.0, 1.0 '; Bottom Right Of The Quad (Top)

glColor3f 1.0,0.5,0.0 '; Set The Color To Orange
glVertex3f 1.0,-1.0, 1.0 '; Top Right Of The Quad (Bottom)
glVertex3f -1.0,-1.0, 1.0 '; Top Left Of The Quad (Bottom)
glVertex3f -1.0,-1.0,-1.0 '; Bottom Left Of The Quad (Bottom)
glVertex3f 1.0,-1.0,-1.0 '; Bottom Right Of The Quad (Bottom)

glColor3f 1.0,0.0,0.0 '; Set The Color To Red
glVertex3f 1.0, 1.0, 1.0 '; Top Right Of The Quad (Front)
glVertex3f -1.0, 1.0, 1.0 '; Top Left Of The Quad (Front)
glVertex3f -1.0,-1.0, 1.0 '; Bottom Left Of The Quad (Front)
glVertex3f 1.0,-1.0, 1.0 '; Bottom Right Of The Quad (Front)

glColor3f 1.0,1.0,0.0 '; Set The Color To Yellow
glVertex3f 1.0,-1.0,-1.0 '; Top Right Of The Quad (Back)
glVertex3f -1.0,-1.0,-1.0 '; Top Left Of The Quad (Back)
glVertex3f -1.0, 1.0,-1.0 '; Bottom Left Of The Quad (Back)
glVertex3f 1.0, 1.0,-1.0 '; Bottom Right Of The Quad (Back)

glColor3f 0.0,0.0,1.0 '; Set The Color To Blue
glVertex3f -1.0, 1.0, 1.0 '; Top Right Of The Quad (Left)
glVertex3f -1.0, 1.0,-1.0 '; Top Left Of The Quad (Left)
glVertex3f -1.0,-1.0,-1.0 '; Bottom Left Of The Quad (Left)
glVertex3f -1.0,-1.0, 1.0 '; Bottom Right Of The Quad (Left)

glColor3f 1.0,0.0,1.0 '; Set The Color To Violet
glVertex3f 1.0, 1.0,-1.0 '; Top Right Of The Quad (Right)
glVertex3f 1.0, 1.0, 1.0 '; Top Left Of The Quad (Right)
glVertex3f 1.0,-1.0, 1.0 '; Bottom Left Of The Quad (Right)
glVertex3f 1.0,-1.0,-1.0 '; Bottom Right Of The Quad (Right)
glEnd

rtri = rtri + 0.02 '; Increase The Rotation Variable For The Triangle ( New )
rquad = rquad + 0.015 '; Decrease The Rotation Variable For The Quad ( New )

context().flushBuffer()

End Method

'prepare the OpenGL context
Method prepare()
Local frame:CCRect = frame()
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glFrontFace(GL_CW)
glShadeModel(GL_SMOOTH)
glViewport(0, 0, frame.size.width, frame.size.height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, frame.size.width / frame.size.height, 1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
End Method


End Type


Foto:
user posted image

Wie man sieht, muss in der Methode view.drawRect(rect:CCRect) gezeichnet werden. Das ist nun mal so bei Cocoa! Gezeichnet wird ausschließlich in draw* Methoden! Wenn ich einen Max2D Treiber schreibe, wird sich das schon noch ändern!

Grüße

buggy

27 - TokenField und Combobox

Samstag, 17. März 2012 von d-bug
Hallo zusammen,

nachdem ich nun das Scintillamonster gebändigt habe, widme ich mich mal wieder den Cocoa Klassen. Als erstes sind dabei CCDockTile, CCTokenField und CCCombobox raus gekommen.

CCTokenField
Im Prinzip kennt die Dinger jeder Mac User aus der Adresszeile von Apple-Mail. Kurz gesagt werden hier Eingaben in Tokens umgewandelt. Gibt man bei Mail z.B. eine Mail-Adresse ein wird sie in den Namen des Kontakts aus dem Adressbuch umgewandelt. Sowas können wir nun auch!

BlitzMax: [AUSKLAPPEN]
		Local tokenField:CCTokenField = CCTokenField.alloc().initWithFrame(frame)
tokenField.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
tokenField.setDelegate(Self)
tokenField.setText("Hund")
view.addSubView(tokenField)

Obriger Code baut ein TokenField und setzt das Token "Hund" aus dem dann "hund@wuff.de" wird (siehe Bild). Wie man das umwandelt, sieht man im nächsten Code:
BlitzMax: [AUSKLAPPEN]
	Method tokenFieldDisplayStringForRepresentedObject:String(tokenField:CCTokenField, representedObject:String)
Select representedObject
Case "Hund"
Return "hund@wuff.de"
End Select
Return representedObject
End Method

Außerdem kann man den Tokens noch ein Menü zuweisen was wie folgt passieren kann:
BlitzMax: [AUSKLAPPEN]
	Method tokenFieldHasMenuForRepresentedObject:Int(tokenField:CCTokenField, representedObject:String)
Select representedObject
Case "Hund"
Return YES
End Select
Return NO
End Method

Method tokenFieldMenuForRepresentedObject:CCMenu(tokenField:CCTokenField, representedObject:String)
Global menu:CCMenu
Local item:CCMenuItem
Select representedObject
Case "Hund"
If Not menu
menu = CCMenu.menu()
menu.addItemWithTitle("Hund",CCNullAction,"",CCNullTarget)
menu.addItemWithTitle("Katze",CCNullAction,"",CCNullTarget)
menu.addItemWithTitle("Maus",CCNullAction,"",CCNullTarget)
EndIf
Return menu
End Select
Return Null
End Method




CCComboBox
Wer kennt nicht die Eingabezeile mit Popup-Menü? Wer die Hand hebt wird erschossen! Jedenfalls gibts die jetzt auch in cocoa.cocoa:
BlitzMax: [AUSKLAPPEN]
		Local comboBox:CCComboBox = CCComboBox.alloc().initWithFrame(frame)
comboBox.setLayout(CCAlignTop | CCAlignLeft | CCAlignWidthSizable)
comboBox.setDelegate(Self)
comboBox.addValues(["Hund", "Katze", "Maus", "Pferd", "Elefant", "Erdnuckel"])
comboBox.insertValue("Nashorn", 2)
comboBox.selectValue("Maus")
view.addSubView(comboBox)

Auch hierzu findet man alles im Bild:
user posted image


CCDockTile
Das Ding ist auch aus AppleMail bekannt. Es zeigt einem die ungelesenen Mails als weiße Zahl in rotem Kreis im DockIcon an. So wirds gemacht:
BlitzMax: [AUSKLAPPEN]
		Local dockTile:CCDockTile = app.dockTile()
dockTile.setBadgeLabel("200")


und so siehts bei maximalen Dock-Zoom Effekt aus (sonst sieht man ja nichts...):
user posted image




Das reicht dann erst mal wieder für heute!

buggy

26 - Umstrukturierung und Neues

Montag, 12. März 2012 von d-bug
Hallo zusammen,

da ich anscheinend zu viel Zeit habe gab es eine paar Umbaumaßnahmen im cocoa.scintilla Modul.

  • SCNMarker wurde durch passende Methoden in der eigentlichen SCNScintillaView Klasse ersetzt.
  • Es kam eine neue Klasse namens SCNLanguageDefinition hinzu. Diese ermöglicht es einem durch Subclassing diverse Anpassungen an den Sprachen die man Unterstützen möchte (siehe Sample) vorzunehmen.
  • SCNKeyword wurde komplett gelöscht und in SCNLanguageDefinition integriert.
  • Unterstützung für Indikatoren kam in SCNScintillaView hinzu.
  • Unterstützung für Multiselection kam in SCNScintillaView hinzu.
  • Such-Funktionalität kam in SCNScintillaView hinzu.
  • Vorgefertigtes Quote-Completion kam mit SCNLanguageDefinition hinzu.
  • Vorgefertigtes Brace-Completion kam mit SCNLanguageDefinition hinzu.
  • Vorgefertigtes Einrücken kam mit SCNLanguageDefinition hinzu.
  • Vorgefertigtes Einrücken für Keywords kam mit SCNLanguageDefinition hinzu.
  • Delegate Methoden für AutoCompletion wurden entfernt und durch Methoden in SCNLanguageDefinition ersetzt.
  • Delegate zum initialisieren von SCNScintillaView nach dem setzen der Sprache mittels scintilla.setLanguage(lang:SCNLanguageDefinition) hinzu. Damit man nicht wie doof da steht weil das Folding nicht mehr funktioniert. So ist es mir passiert, weil ich die Reihenfolge der Initialisierung im Sample änderte.


So, dass wars auch im großen und ganzen. Im Moment bin ich dabei die Style-Methoden von Scintilla auch mal in die SCNScintillaView zu übernehmen. Danach wird wohl auch die SCNStyle-Klasse vereinfacht werden bzw. entfallen. Vielleicht werd ich sie aber auch mit in SCNLanguageDefinition packen. Dann hat man alles auf einem Fleck und kann recht einfach eine Sprache implementieren.

Außerdem habe ich noch auf BlitzMax 1.47 nebst XCode 4.3.1 geupdated. Erstaunlicher Weise war das total einfach. Nach dem letzten Disaster hatte ich eigentlich tonnenweise Abstürze, Inkompatibilitäten und dergleichen erwartet. Allerdings kam da gar nichts!

So, jetzt noch ein Sample der neusten Umstrukturierungen. Hier mit der BlitzMax Erweiterung von SCNLanguageDefinition.
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.scintilla
Import brl.pngloader
Import brl.textstream

Global testText:String = LoadText("test.bmx")

'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
Field view:SCNScintillaView

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

'create the style for the BlitzBasic lexer
Local style:SCNStyle = SCNStyle.alloc().init()
style.setLexerStyle(SCLEX_BLITZMAX, CCFont.systemFontOfSize(CCFont.systemFontSize()), CCColor.textBackgroundColor(), CCColor.textColor())
style.setKeywordStyle(SCE_BMX_KEYWORD, CCColor.blueColor(), YES, NO, NO)
style.setKeywordStyle(SCE_BMX_NUMBER, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_COMMENT, CCColor.grayColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_MULTICOMMENT, CCColor.grayColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_LABEL, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_STRING, CCColor.greenColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_OPERATOR, CCColor.textColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_PREPROCESSOR, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_COMPILER, CCColor.orangeColor(), NO, NO, NO)


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

'create and intitalize Scintilla view
view = SCNScintillaView.alloc().initWithFrame( window.contentView().frame())
view.setDelegate(Self)
view.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)

'set the language to use in the current scintilla instance
'this must be done before the folding is initialized. Otherwise the folding does not show.
view.setLanguage(SCNBlitzMax.alloc().init())

'add scintilla to the windows content view
window.contentView().addSubView(view)
window.show()


'set the loaded text to scintilla
view.setText(testText)

'set some annotations
view.setAnnotation(4, "Hund~nKatze", "1")
view.setAnnotation(5, "Hundefutter~nKatzenfutter~nErdnuckelfutter", "2")



'set some indicators
view.indicatorSetStyle(1, INDIC_STRAIGHTBOX)
view.indicatorSetForegroundColor(1, CCColor.redColor())
view.indicatorSetCurrent(1)
view.indicatorFillRange(10,10)
view.indicatorFillRange(30,10)

view.setMultipleSelection(NO)

End Method



'use this delegate to initialize scintilla after changing the language (lexer)
Method scintillaDidChangeLanguage(view:SCNScintillaView, language:SCNLanguageDefinition)

'set word chars
view.setWordChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

'enable caret line
view.setShowsCaret(YES)

'enable white spaces
view.setShowsWhiteSpaces(NO)

'disable linefeeds
view.setShowsLineFeeds(NO)

'initialize line-number margin
view.marginSetType(1, SC_MARGIN_NUMBER)
view.marginSetWidth(1, view.TextWidth(STYLE_LINENUMBER, "_99999"))

'initialize folding-margin
view.marginSetType(2, SC_MARGIN_SYMBOL)
view.marginSetMask(2, SC_MASK_FOLDERS)
view.marginSetWidth(2, 16)
view.marginSetSensitive(2, YES)

'initialize folding markers
view.markerDefine(SC_MARKNUM_FOLDER, SC_MARK_ARROW)
view.markerDefine(SC_MARKNUM_FOLDEROPEN, SC_MARK_ARROWDOWN)
view.markerDefine(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY)
view.markerDefine(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY)
view.markerDefine(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY)
view.markerDefine(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY)
view.markerDefine(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY)
view.markerSetBackgroundColor(SC_MARKNUM_FOLDER, CCColor.grayColor())
view.markerSetForegroundColor(SC_MARKNUM_FOLDER, CCColor.grayColor())
view.markerSetBackgroundColor(SC_MARKNUM_FOLDEROPEN, CCColor.grayColor())
view.markerSetForegroundColor(SC_MARKNUM_FOLDEROPEN, CCColor.grayColor())

'set folding properties
view.setProperty("fold","1") 'enables folding
view.setProperty("fold.compact","0")

'enable indentation guides
view.setShowsIndentationGuides(YES)

End Method


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

Method CCTextDidChangeNotification(notification:CCNotification)
End Method


End Type


'This is the language definition for BlitzMax
Type SCNBlitzMax Extends SCNLanguageDefinition

Function alloc:SCNBlitzMax()
Return New SCNBlitzMax
End Function

Method lexer:Int()
Return SCLEX_BLITZMAX
End Method

'returns YES if the char is a brace
Method charIsBrace:Int(char:Int)
Select char
Case 40,41,91,93,123,125
Return YES
End Select
Return NO
End Method

'returns YES if the char is a quote
Method charIsQuote:Int(char:Int)
Return char = 34
End Method

'returns YES on indentation of "Function", "Method" and "Type"
Method indentsForLine:Int(lineString:String)
Select lineString.Trim().split(" ")[0].toLower()
Case "function","method","type"
Return YES
End Select
Return NO
End Method

Method init:SCNBlitzMax()
Return Self
End Method

'returns YES if the current style is a comment
Method isComment:Int(style:Int)
Select style
Case SCE_BMX_MULTICOMMENT, SCE_BMX_COMMENT
Return YES
End Select
Return NO
End Method

'returns the keywords for a given lexer constant
'the list argument depends on the lexer.
'in BlitzMax list numbers are: 0 = SCE_BMX_KEYWORD ; 1 = SCE_BMX_KEYWORD2 ; 2 = SCE_BMX_KEYWORD3 ; 3 = SCE_BMX_KEYWORD4
'there can be up to 7 different keyword lists which depends on the lexer too.
Method keywords:String(list:Int)
Select list
Case 0
Return "function method type end local global if"
End Select
End Method

'returns YES if brace matching is supported
Method supportsBraceMatching:Int()
Return YES
End Method

Method supportsBraceCompletion:Int()
Return YES
End Method

'returns YES if indentation is supported
Method supportsIndentation:Int()
Return YES
End Method

'returns YES if indentation for language keywords is supported
Method supportsKeywordIndentation:Int()
Return YES
End Method

'returns YES if quote completion is supported
Method supportsQuoteCompletion:Int()
Return YES
End Method

'returns YES for unindentation of "EndFunction", "End Function", "EndMethod", "End Method"...
Method unindentsForLine:Int(lineString:String)
Local lineArray:String[] = lineString.Trim().toLower().split(" ")
Select lineArray[0]
Case "endfunction","endmethod","endtype"
Return YES
Case "end"
Select lineArray[1]
Case "function","method","type"
Return YES
End Select
End Select
Return NO
End Method

End Type



Heute mal ohne Bild, denn das lohnte sich nicht.


Grüße!

25 - Annotations und Brace-Matching

Samstag, 10. März 2012 von d-bug
Hallo zusammen,

heute gibts noch nicht all zu viel zu berichten.

Annotations
Das ist eine Art Notiz, die zwischen Zeilen gequetscht wird.

Man kann bis zu 256 Annotation Style-Kategorien im SCNDefaultStyle anlegen. Sie sollten als Key folgenden Namen haben: "annotationStyle0" oder "annotationStyle12" usw.

BlitzMax: [AUSKLAPPEN]
SCNDefaultStyle.setKeywordStyle("annotationStyle0", CCColor.colorFromRGB($000000), NO, YES, NO, SC_CASE_MIXED, CCFont.systemFontOfSize(CCFont.smallSystemFontSize()), CCColor.colorFromRGB($efefef))
usw... (Das YES soll übrigens heißen, dass das in Italic dargestellt werden soll. Macht die Sau aber nicht!)

Mit textView.setAnnotation(line, text, style) kann man dann den Style zuweisen. Dabei wird allerdings nur der Index angegeben. Bei den Beispielen also "0" oder "12". Sollte es mir irgendwann gelingen einen String auch in eine gültiges char array zu konvertieren, dann kann man für jeden Char einen eigenen Style angeben. Unnötig? Naja, man kann dann eben verschiedene Arten von Notizen zeilenweise unterschiedlich einfärben, oder dergleichen eben. Scintilla bietet das ja schon an, allerdings bekomme ich eben die Konvertierung nicht hin.

BlitzMax: [AUSKLAPPEN]
textView.setAnnotation(4, "Hund~nKatze", "1")
textView.setAnnotation(5, "Hundefutter~nKatzenfutter~nErdnuckelfutter", "2")


user posted image



Brace-Matching
Naja, dazu gibt es nun echt nicht viel zu sagen. Scintilla vergleicht eben die Anzahl der einleitenden Klammern mit der Anzahl der schließenden Klammern und malt sie bunt, wenn es passt oder anders bunt wenn es nicht passt. Dazu kann für jeden Lexer ein String mit den Klammern gesetzt werden. Ist der String nicht vorhanden, wird eben das Brace-Matching nicht ausgeführt.

BlitzMax: [AUSKLAPPEN]
textView.setBraces(SCLEX_BLITZMAX, "()[]{}")




Das ist auch schon alles.

Grüße!

24 - Jetzt kommt Farbe ins Spiel!

Sonntag, 4. März 2012 von d-bug
Hallo zusammen,

nachdem ich jetzt mehrere Tage gehext habe, präsentiere ich nun die neusten Ergebnisse:

  • Das Notification-System ist implementiert. Hier wird bei jeder kleinen Aktion von Scintilla die CCTextDidChangeNotification ausgelöst die eine Erweiterung der CCNotification-Klasse ist und alle Variablen des Scintilla eigenen SCNotification Structs enthält.
  • Die Styles wurden noch mal komplett umgeschrieben. Es kann jetzt einen Style pro Lexer geben, der beim setzen des Lexers mittels scintilla.setLexer(LEXER) automatisch gesetzt wird. Dazu gibts noch einen Style, der die Umgebungs-Farben und Fonts enthält (z.B. Zeilennummerierung usw.)
  • Die Keywords wurden ebenfalls noch mal angepasst. Auch die werden jetzt automatisch mit scintilla.setLexer(LEXER) gesetzt.
  • Folding ist jetzt auch drin! Allerdings nur als Standbild, denn anklicken kann man da noch nichts.
  • Da das Framework keinen BlitzMax Lexer hatte, habe ich den jetzt auch noch eingefügt. Hierbei habe ich mich unverschämter weise an Bruceys wxScintilla Lexer vergangen. Dieser wurde zwar für eine ältere Version von Scintilla geschrieben, konnte aber durch anpassen der Includes zum laufen gebracht werden. Ein zwei Änderungen daran habe ich allerdings auch noch vorgenommen. Folding für Rem-Blöcke und diverse Konstanten sind extra!


Ergebnis des ganzen:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.scintilla
Import brl.pngloader


'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
Field textView:SCNScintillaView

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

'create some keywords for the BlitzBasic lexer
Local keyword:SCNKeyword
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "Function")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "End")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "Type")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "If")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "Local")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "Int")
keyword = SCNKeyword.alloc().init(SCLEX_BLITZMAX, 0, "String")


'create the style for the BlitzBasic lexer
Local style:SCNStyle = SCNStyle.alloc().init()
style.setLexerStyle(SCLEX_BLITZMAX, CCFont.systemFontOfSize(CCFont.systemFontSize()), CCColor.textBackgroundColor(), CCColor.textColor())
style.setKeywordStyle(SCE_BMX_KEYWORD, CCColor.blueColor(), YES, NO, NO)
style.setKeywordStyle(SCE_BMX_NUMBER, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_COMMENT, CCColor.grayColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_MULTICOMMENT, CCColor.grayColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_LABEL, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_STRING, CCColor.greenColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_OPERATOR, CCColor.textColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_PREPROCESSOR, CCColor.orangeColor(), NO, NO, NO)
style.setKeywordStyle(SCE_BMX_COMPILER, CCColor.orangeColor(), NO, NO, NO)


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

textView = SCNScintillaView.alloc().initWithFrame( window.contentView().frame())
textView.setDelegate(Self)
textView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)
textView.setWordChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

'enable caret line
textView.setShowsCaret(YES)

'enable white spaces
textView.SetShowsWhiteSpaces(YES)

'disable linefeeds
textView.setShowsLineFeeds(NO)

'enable line numbers
textView.setShowsLineNumbers(YES)

'enable folding margin
textView.setShowsFolding(YES)

'set the lexer (this applies the style and keywords for this lexer too)
textView.setLexer(SCLEX_BLITZMAX)

textView.setProperty("fold","1")
textView.setProperty("fold.compact","0")

window.contentView().addSubView(textView)

window.show()

'textView.setSelected(textView.positionFromLine(1)+3,textView.positionFromLine(1)+3)
'textView.autocomplete()
End Method

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


'return a modified list of suggestions for auto-completion
Method scintillaViewCompletionsForPartialWord:TList(view:SCNScintillaView, word:String, suggestions:TList)
Return suggestions

End Method

'use this delegate to avoid completions in a unwanted range; return YES to allow completion, otherwise NO
Method scintillaViewShouldShowCompletionsForWordAtRange:Int(view:SCNScintillaView, word:String, range:CCRange)
Return YES
End Method

Method CCTextDidChangeNotification(notification:CCNotification)
Local scn:SCNNotification = SCNNotification(notification)
Select scn.code
Case SCN_PAINTED, SCN_UPDATEUI
Default
CCLog(scn)
End Select
End Method


End Type

user posted image
Alles so schön bunt jetzt... So richtig funktioniert es eh noch nicht, aber daran wird weiter gearbeitet!



Nad dann, schönen Restsonntag wünsch ich noch,

buggy

23 - AutoCompletion und Keywords

Donnerstag, 1. März 2012 von d-bug
Hallo zusammen,

letzterdings hab ich mich mal mit AutoCompletion in Scintilla auseinander gesetzt! Dazu benötigt es natürlich auch ein paar Keywords, aus denen Scintilla auswählen kann. Hierzu gibt es nun die SCNKeyword Klasse.

SCNKeyword wird in einem CCDictionary gespeichert das wiederum in einem Array mit der Lexer-Nummer abgelegt ist. Somit kann man x-beliebig viele Keywords pro Lexer definieren. SCNKeyword selbst beinhaltet ein paar Daten für Scintilla und evtl. Erweiterungen. Als Vorlage nahm ich hier die Keyword-Klasse von ChaosEdit, die auch den Link zur Hilfe, die Parameter der etwaigen Funktion, die Keyowrd-Konstante von Scintilla und die Beschreibung des Befehls enthält. Wie man das jetzt nutzt bleibt jedem selbst überlassen. Momentan werden Keywords noch nicht eingefärbt, aber das wird sich bald legen.

Eine Keyword-Definition könnte so aussehen...
BlitzMax: [AUSKLAPPEN]
Local keyword:SCNKeyword = SCNKeyword.alloc().init(SCLEX_BLITZBASIC, SCE_B_KEYWORD, "Erdnuckel")

... kann aber durch Subclassing von SCNKeyword top angepasst werden.



Nach den Keywords hab ich dann direkt AutoCompletion integriert. Dazu musste ich mir erst mal ein Update des scintilla.frameworks organisieren, weil in meinem veralteten Stand so einiges noch fehlte. Unter anderem auch die Table-View für die AutoCompletion-Liste...

BlitzMax: [AUSKLAPPEN]
'Den Cursor hinter die ersten drei Buchstaben von Hund bewegen...
textView.setSelected(textView.positionFromLine(1)+3,textView.positionFromLine(1)+3)
'Triggern der AutoCompletion-Liste
textView.autocomplete()


user posted image



Yep! Yep! Das wars auch schon wieder...

buggy




P.S.: Kleiner Aufruf:
KLEPTOOOOOOO ich brauch noch mal deinen BlitzMax Lexer! Also die .cxx Datei... Hab den vom letzten mal verschlampt. :/

22 - Problem erkannt, Problem gebannt

Sonntag, 26. Februar 2012 von d-bug
Hallo zusammen,

einem Update auf XCode 4.3 und mehrfachem lesen der folgenden Threads von bb.com...
http://www.blitzbasic.com/Comm...opic=96997
http://www.blitzbasic.com/Comm...opic=96152
http://www.blitzbasic.com/Comm...opic=96562

...einem erneuten Downgrade auf XCode 4.2.1 und einem Upgrade auf BlitzMax 1.46 kann ich nun folgendes Berichten:
BlitzMax 1.44, auf dem ich bislang die Cocoa Module schrieb, funktioniert jetzt nicht mehr! XCode 4.3 und BlitzMax 1.46 funktionieren ebenfalls nicht zusammen, aber XCode 4.2.1 und BlitzMax 1.46 verrichten ihren Dienst wieder.

Die besagten Fehler blieben aber auch nach der Installations-Orgie erhalten... :/

Also hab ich mich noch mal durch den Code gefressen und mir ist aufgefallen, dass der Fehler immer nur dann Auftrat, wenn ich die Methode frame() aufgerufen habe. Komisch! Also mal die ganze Frame-Geschichte näher Untersucht. In core.m wurde ich dann fündig.

Statt:
Code: [AUSKLAPPEN]
NSRect result = NSMakeRect(0.0,0.0,0.0,0.0);
objc_msgSend_stret(&result, obj, NSSelectorFromString(NSStringFromBBString(message)));
return CCRectFromNSRect(result);}

müsste es eigentlich:
Code: [AUSKLAPPEN]
NSRect result = (*(NSRect(*)(id, SEL, ...))objc_msgSend_stret)(obj, NSSelectorFromString(NSStringFromBBString(message)));
return CCRectFromNSRect(result);

Na gut... Ich gebe zu, dass ich beides aus dem Netz gezogen habe ohne zu wissen, was ich da tu.


Wie dem auch sei, das Problem ist hiermit behoben! Warum die Fehlermeldung auf brl.reflections zeigte ist mir nach wie vor nicht klar, spielt aber auch keine Rolle mehr! Jedenfalls muss ich jetzt keine größeren Änderungen mehr vornehmen und kann weiter machen wie gehabt. \o/

Grüße

21 - Scintilla #2 und die modulare Apokalypse

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

erst mal zum angenehmen Teil:

Scintilla kann nun Zeilennummerierung und Markierungen dazu eine Erweiterung zum letzten Sample...
BlitzMax: [AUSKLAPPEN]
		'enable line numbers
textView.setShowsLineNumbers(YES)

'marking the line with a small red rect to the left of the margin
Local marker:SCNMarker = SCNMarker.alloc().init()


marker.setBackgroundColor(CCMakeColor(1.0,0.0,0.0,0.05))
marker.setSymbol(SC_MARK_LEFTRECT)
textView.addMarker(0, marker)

'adding an arrow
marker = SCNMarker.alloc().init()
marker.setSymbol(SC_MARK_SHORTARROW)
textView.addMarker(3, marker)


...und natürlich ein Bild...
user posted image
Das rote Rechteck, der Buchstabe und der Pfeil sind die Markierungen. Die Zeilennummerierung sollte selbsterklärend sein.




Jetzt zum unangenehmen Teil:

Tja, lang lebe BRL und lang lebe deren Reflections-Modul! Ich hab vorhin mal probiert ein/zwei Samples im Release-Mode zu kompilieren bzw. auszuführen! Als erstes das Scintilla-Sample... BAMM Absturz mit einem Hinweis auf brl.reflections, aber ohne ordentliche Meldung. Als nächstes das TextView-Sample... BAMM^2! Dann das Segmented-Control-Sample... Top, funktioniert, allerdings liegen alle 3 Controls übereinander :O... usw... usw... usw...

Mein nächster Ansatz: XCode 4.3 installiert, BlitzMax 1.46 installiert... Ergebnis: Jedes Kompilat im Release-Mode wird mit der Meldung "ld: library not found for -lcrt1.o" honoriert... Na super!

Folgende Lösungen habe ich nun parat:

  • Ich schmeiß es vor lauter Wut hin, aber dazu ist mir die ganze Arbeit einfach zu schade...
  • Ich verzichte auf brl.reflections und muss alle Notifications, Events, Target/Action und Delegates umschreiben zu Function-Callbacks und einer vorgefertigten Controllerklasse, die bereits alle nötigen Methoden als Dummies enthält. Eine Horror-Arbeit, aber einer muss sie ja tun (höhö)
  • Ich verlasse mich darauf das BRL mal aus den Puschen kommt und sich mal wieder intensiv auf BlitzMax stürzt und fixt, fixt, fixt.... Ja klar *zwinker*!
  • Ich besauf mich, obwohl ich normaler weise nichts trinke, bis zur Besinnungslosigkeit und kompiliere fortan nur noch im Debug-Mode...

Ich tendiere zu 2 und einem Downgrade auf XCode 4.2 nebst BlitzMax 1.44, so wie es vorher war!



So, das war es auch schon wieder...

20 - SCNScintillaView #1

Sonntag, 19. Februar 2012 von d-bug
Hallo zusammen,

heute habe ich mit einem wahren Monster begonnen. Das Monster heißt Scintilla und stellt die eindeutig bessere TextView dar. Sie unterstützt diverse Features, die in der original TextView von Cocoa nicht mal angeschnitten werden. So kann man z.B. Folding nutzen, oder Zeilennummerierung... Das waren nur zwei winzige Features des ganzen Pakets. Da das Scintilla.framework in Objective-C++ geschrieben wurde, ist das Wrappen ein wenig komplizierter als bei normalem Objective-C.

Da ich damit rechne, dass das Wrappen von Scintilla einige Worklog-Einträge in Anspruch nehmen wird schneide ich erst mal kurz hier an und zeig euch ein Bild.

Momentan habe ich eigentlich nur die eigentliche View und ein Message-System geschrieben. Außerdem habe ich die ersten ca. 40 Methoden geschrieben und mich um ein einfaches Style-System gekümmert. Letzteres sieht wie folgt aus:

SCNStyle ist eine Erweiterung von CCDictionary, also auch eine Erweiterung von TMap. Man kann also einfach eine Variable unter einem "Pseudonym" in dem Style ablegen. Diese "Pseudonyme" sind festgelegt und beinhalten Font-und Farb-Daten. Mit der neuen Methode SCNStyle.apply(scintillaView) kann man nun einer Instanz der SCNScintillaView diesen Style einfach zuweisen. Ein Beispiel anhand des default Styles:
BlitzMax: [AUSKLAPPEN]
Global SCNDefaultStyle:SCNStyle = SCNStyle.alloc().init()

'default selection style
SCNDefaultStyle.setValueForKey(CCColor.selectedTextColor(), "selectionForegroundColor")
SCNDefaultStyle.setValueForKey(CCColor.selectedTextBackgroundColor(), "selectionBackgroundColor")

'default ehite space style
SCNDefaultStyle.setValueForKey(CCColor.grayColor(), "whiteSpaceForegroundColor")

'default caret style
SCNDefaultStyle.setValueForKey(CCMakeColor(0.95,0.95,0.95,1.0), "caretBackgroundColor")

Die SCNScintillaView haut sich den globalen SCNDefaultStyle beim Initialisieren selbst rein, also muss man sich darum gar nicht kümmern. Außerdem kann man den Style so einfach als eine pList speichern und auch wieder laden. (Ich glaube man merkt, was ich im Hinterkopf habe...)


Als nächstes noch ein Beispiel der Initialisierung der SCNScintillaView:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.scintilla


'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
Field textView:SCNScintillaView





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

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

textView = SCNScintillaView.alloc().initWithFrame(window.contentView().frame())
textView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)

textView.setText(" Hund~nKatze~nMaus~nPferd~nElefant")
textView.insertText("Maulwurf~n",0)
textView.appendText("~nErdnuckel")

textView.setShowsCaret(YES)
textView.SetShowsWhiteSpaces(YES)
textView.setShowsLineFeeds(NO)

window.contentView().addSubView(textView)

window.show()

End Method

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

End Type

Noch gibt ess keine Delegates oder Notifications zu bewundern.

Noch flott ein Bild:
user posted image
Noch nicht sehr aussagekräftig, aber immerhin sieht man schon mal ein wenig Text und WhiteSpaceSupport.

Ich denke ich habe Scintilla erst mal nur angekratzt. Da ist noch jede Menge Zeugs zu wrappen. Aber nun mach ich erst mal Schluss für heute!

Schönen Tag noch!

19 - PSMTabBarControl Framework

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

wer kennt sie nicht, die Tabs in Safari? Es ist und bleibt ein, von Apple, selbst gefrickeltes Gadget, zu dem es keine vorgefertigte Klasse in Cocoa gibt. Ein findiger Programmierer namens John Pannell hat dazu im Jahre 2005 eine Abhilfe geschaffen. Diese kommt in Form eines Frameworks daher und hört auf den Namen PSMTabBarControl! Seit dem ist viel Zeit vergangen und man findet das Framework und hundert verschiedenen Versionen im Netz. Jeder meint er müsse mal darin rumfummeln (ich auch :>) und es dann als Repository irgendwo hosten. Es ist aber auch so, dass das original Framework schon seit Leopard nicht mehr 100%ig kompatibel zu Cocoa ist. Man muss also ein wenig suchen um eines zu finden, dass auch unter Lion noch läuft.

Ich hatte dieses Framework schon mal gewrappt, als ich meinen ersten Versuch startete Cocoa vernünftig in BlitzMax einzubinden. Gott sei Dank läuft die damalige Version des Frameworks, die schon auf Snow Leopard entstand, auch jetzt noch tadellos. Bisher gibt es zwar ein paar Versionen, die auf Lion zugeschnitten sind, aber in die konnte ich meinen persönlichen Tab-Style nicht einpflanzen. Als nahm ich doch wieder meine alte Version!

Außerdem hab ich die letzte Woche an einem Fehler im Modul gesucht, denn ich konnte zwar den Plus-Button nutzen, aber die Tabs wurden nicht in der Leiste angezeigt. Heute ist mir dann aufgefallen, dass ich lediglich vergessen hatte den richtigen Controller für die verlinkte TabView zu setzen. So etwas ist ärgerlich und gehört bestraft. *in die Ecke stell*

So, lange Rede kurzer Code:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework cocoa.psmtabbarcontrol


'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 tabView:CCTabView
Field tabbar:PSMTabbarControl


Method addTab(sender:CCObject)
Local item:CCTabViewItem
Local identifier:PSMTabbarIdentifier

identifier = PSMTabbarIdentifier.alloc().init()
identifier.setCount(2)
identifier.setImage(CCImage.imageNamed("NSImageNameStatusAvailable"))

item = CCTabViewItem.alloc().initWithIdentifier(identifier)
item.setContentView((New CCView).initWithFrame(tabView.contentRect()))
item.setTitle("Untitled")
tabView.addItem(item)
tabView.selectItem(item)

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()

frame = window.contentView().frame()

'create tabbar
frame.size.height = 22.0
tabbar = PSMTabbarControl.alloc().initWithFrame(frame)
tabbar.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable)
tabbar.setDelegate(Self)
tabbar.setStyleNamed("Chaos")
tabbar.setShowAddTabButton(YES)
tabbar.setCellMinWidth(100)
tabbar.setCellMaxWidth(280)
tabbar.setCellOptimumWidth(130)
tabbar.addTabButton().setTarget(Self)
tabbar.addTabButton().setAction("addTab")
window.contentView().addSubView(tabbar)

'create tabview
frame = window.contentView().frame()
frame.origin.y:+22.0 ; frame.size.height:-22.0
tabView = (New CCTabView).initWithFrame(frame)
tabView.setLayout(CCAlignLeft | CCAlignTop | CCAlignWidthSizable | CCAlignHeightSizable)
tabbar.setTabView(tabView)
window.contentView().addSubView(tabView)


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


Und natürlich ein Bild:
user posted image

Die obere Leiste ist die PSMTabbarControl und die untere die normalen Cocoa Tabs. Wie man sieht kann man den Tabs damit auch Bilder zuweisen (der grüne Punkt), die Leiste läuft nicht mehr über, wenn man es denn so will, man kann Add-und Closebuttons haben oder sogar Badges mit Zahlen! Nicht im Bild ist der Progressindicator, der jedem Tab zugewiesen werden kann!

Keine Panik, man kann die original Tab-Leiste auch ausblenden lassen. Dies habe ich nur aus Testzwecken hier nicht getan!

Jetzt muss ich das ganze nur noch dokumentieren... *seufz*



Bis zum nächsten mal!

buggy

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