Page 1 of 1

NSPenel

Posted: Mon Dec 15, 2014 11:30 pm
by Wolfram
Hi,

can anybody tell me how to program a NSPanel like this.
Image

I tried this, but it dose not work as expected.

Code: Select all

#NSUtilityWindowMask  = 1 << 4
#NSDocModalWindowMask  = 1 << 6
#NSNonactivatingPanelMask  = 1 << 7
#NSHUDWindowMask  = 1 << 13


Window_0 = OpenWindow(#PB_Any, 100, 300, 100, 300, "v")

NSPanel = WindowID(Window_0)

CocoaMessage(0, NSPanel, "setStyleMask:", #NSUtilityWindowMask) 


Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: NSPenel

Posted: Tue Dec 16, 2014 7:35 pm
by Danilo
What do you mean? If you want a smaller title bar height (for tool windows), you need to use NSPanel directly:

Code: Select all

Enumeration CGWindowLevelKey
   #kCGBaseWindowLevelKey = 0
   #kCGMinimumWindowLevelKey
   #kCGDesktopWindowLevelKey
   #kCGBackstopMenuLevelKey
   #kCGNormalWindowLevelKey
   #kCGFloatingWindowLevelKey
   #kCGTornOffMenuWindowLevelKey
   #kCGDockWindowLevelKey
   #kCGMainMenuWindowLevelKey
   #kCGStatusWindowLevelKey
   #kCGModalPanelWindowLevelKey
   #kCGPopUpMenuWindowLevelKey
   #kCGDraggingWindowLevelKey
   #kCGScreenSaverWindowLevelKey
   #kCGMaximumWindowLevelKey
   #kCGOverlayWindowLevelKey
   #kCGHelpWindowLevelKey
   #kCGUtilityWindowLevelKey
   #kCGDesktopIconWindowLevelKey
   #kCGCursorWindowLevelKey
   #kCGAssistiveTechHighWindowLevelKey
   #kCGNumberOfWindowLevelKeys
EndEnumeration

#NSFloatingWindowLevel          = #kCGFloatingWindowLevelKey


#NSBorderlessWindowMask         = 0
#NSTitledWindowMask             = 1 << 0
#NSClosableWindowMask           = 1 << 1
#NSMiniaturizableWindowMask     = 1 << 2
#NSResizableWindowMask          = 1 << 3
#NSUtilityWindowMask            = 1 << 4
#NSDocModalWindowMask           = 1 << 6
#NSNonactivatingPanelMask       = 1 << 7
#NSTexturedBackgroundWindowMask = 1 << 8
#NSHUDWindowMask                = 1 << 13

w1=OpenWindow(#PB_Any, 80, 280, 100, 300, "v")
;Window_0 = OpenWindow(#PB_Any, 100, 300, 150, 300, "Utility");,WindowID(w1))
;NSPanel = WindowID(Window_0)

Procedure App()
    Protected app
    CocoaMessage(@app,0,"NSApplication sharedApplication")
    ProcedureReturn app
EndProcedure

Procedure InitRect(*rect.NSRect,x,y,width,height)
    If *rect
        *rect\origin\x = x
        *rect\origin\y = y
        *rect\size\width = width
        *rect\size\height = height
    EndIf
EndProcedure


Procedure Panel(x,y,width,height,title.s,mask,center=0)
    Protected size.NSSize, rect.NSRect, win, view
    CocoaMessage(@win,0,"NSPanel alloc")
    If win
        InitRect(@rect,x,y,width,height)
        CocoaMessage(0,win,"initWithContentRect:@",@rect,"styleMask:",mask,"backing:",2,"defer:",#NO)
        ;CocoaMessage(0,win,"makeKeyWindow")
        CocoaMessage(0,Win,"makeKeyAndOrderFront:",App())
        CocoaMessage(0,win,"setTitle:$",@title)
        ;InitSize(@size,width,height)
        ;CocoaMessage(0,win,"setMinSize:",size)
        
        CocoaMessage(0,win,"setPreventsApplicationTerminationWhenModal:",#NO)
        CocoaMessage(0,win,"setReleasedWhenClosed:",#YES)
        
        CocoaMessage(@view,0,"NSView alloc")
        If view
            InitRect(@rect,0,0,width,height)
            CocoaMessage(@view,view,"initWithFrame:@",@rect)
            CocoaMessage(0,win,"setContentView:",view)
        EndIf
        
        If center
            CocoaMessage(0,win,"center")
        EndIf
        CocoaMessage(0,win,"update")
        CocoaMessage(0,win,"display")
    EndIf
    ProcedureReturn win
EndProcedure


Procedure OnBtnClick()
    End
EndProcedure

NSPanel = Panel(100,300,200,300,"Utility",#NSUtilityWindowMask|
                                          #NSTitledWindowMask|
                                          #NSClosableWindowMask|
                                          #NSMiniaturizableWindowMask|
                                          ;#NSTexturedBackgroundWindowMask|
                                          ;#NSNonactivatingPanelMask|
                                          #NSResizableWindowMask)

;CocoaMessage(0, NSPanel, "setStyleMask:", #NSUtilityWindowMask|
;                                          #NSTitledWindowMask|
;                                          #NSClosableWindowMask|
;                                          #NSMiniaturizableWindowMask|
;                                          ;#NSTexturedBackgroundWindowMask|
;                                          #NSResizableWindowMask) 

;CocoaMessage(0, NSPanel, "setFloatingPanel:",#YES)
;CocoaMessage(0, NSPanel, "setShowsResizeIndicator:",#YES)
CocoaMessage(0, NSPanel, "setMovableByWindowBackground:",#YES)
CocoaMessage(0, NSPanel, "setLevel:",#NSFloatingWindowLevel) ; stay on top

UseGadgetList( NSPanel )
ButtonGadget(1,10,10,150,25,"eXit")

BindGadgetEvent(1,@OnBtnClick())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: NSPenel

Posted: Tue Dec 16, 2014 8:02 pm
by Wolfram
It seams you speak my language and Cocoa too ;-)

Thanks!

Re: NSPenel

Posted: Tue Dec 16, 2014 11:09 pm
by Wolfram
To set the y position of the Panel like you do it in PB you must change this

Code: Select all

Procedure InitRect(*rect.NSRect,x,y,width,height)
  Protected High
  ExamineDesktops()
  High = DesktopHeight(0) - y - height -22
  
    If *rect
        *rect\origin\x = x
        *rect\origin\y = High
        *rect\size\width = width
        *rect\size\height = height
    EndIf
EndProcedure

Re: NSPenel

Posted: Wed Dec 17, 2014 12:07 am
by Danilo
It depends on how many desktops, with different screen resolutions, you (or your customers) have.

Easiest thing is to overwrite the "isFlipped" method, if you want the co-ordinates like on Windows OS.
In Mac OS X, co-ordinates begin on bottom left, instead top left (like on Windows), by default.

Simple Cocoa code that demonstrates the "isFlipped" override:

Code: Select all

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>


@interface MyWindowDelegate : NSObject<NSWindowDelegate>
@end

@implementation MyWindowDelegate
    - (BOOL)windowShouldClose:(id)window {
        [window release];
        NSApplication *app = [NSApplication sharedApplication];
        [app terminate:app];
        return YES;
    }

    - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
        return NSTerminateNow;
    }

    //- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
    //    return NSMakeSize(frameSize.width,frameSize.width*0.5);
    //}
@end

@interface MyNSView : NSView
@end

@implementation MyNSView
    - (BOOL)isFlipped {
        return YES;
    }
    - (BOOL)preservesContentDuringLiveResize {
        return YES;
    }

    - (void) setFrameSize:(NSSize)newSize {
        [super setFrameSize:newSize];

        // A change in size has required the view to be invalidated.
        if ([self inLiveResize])
        {
            NSRect rects[4];
            //int _count;
            NSInteger _count;
            [self getRectsExposedDuringLiveResize:rects count:&_count];
            while (_count-- > 0)
            {
                [self setNeedsDisplayInRect:rects[_count]];
            }
        }
        else
        {
            [self setNeedsDisplay:YES];
        }
    }

@end


class Window {
private:
    String _title;
    int    _x, _y, _width, _height;
    // internal
    NSWindow *_window;
public:
    // Constructors
    static Window* Create(int x, int y, int width, int height, String title) {
        Window* newWindow = new Window();
        newWindow->Title(title);
        newWindow->X(x);
        newWindow->Y(y);
        newWindow->Width(width);
        newWindow->Height(height);
        return newWindow;
    }

    // Properties
    void   Title(const String& title) { this->_title = title;   }
    String Title()                    { return this->_title;    }

    void   X(int x)                   { this->_x = x;           }
    int    X()                        { return this->_x;        }

    void   Y(int y)                   { this->_y = y;           }
    int    Y()                        { return this->_y;        }

    void   Width(int width)           { this->_width = width;   }
    int    Width()                    { return this->_width;    }

    void   Height(int height)         { this->_height = height; }
    int    Height()                   { return this->_height;   }

    // Functions
    void Show() {
        NSApplication *app = [NSApplication sharedApplication]; 
        unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask;
        
        this->_window = [ [NSWindow alloc]
                          initWithContentRect:NSMakeRect(this->_x, this->_y, this->_width, this->_height) 
                          styleMask:styleMask
                          backing:NSBackingStoreBuffered
                          defer:NO
                        ];
        
        MyWindowDelegate *delegate = [[MyWindowDelegate alloc]init];
        [this->_window setDelegate:delegate];

        [this->_window setTitle:this->_title.ToNSString()]; 

        [this->_window setAcceptsMouseMovedEvents:YES];
        [this->_window setPreventsApplicationTerminationWhenModal:NO]; 
        [this->_window setReleasedWhenClosed:YES]; 
        
        MyNSView *view = [[MyNSView alloc]initWithFrame:NSMakeRect(this->_x, this->_y, this->_width, this->_height)];
        [this->_window setContentView:view];

        NSButton *btn1 = [[NSButton alloc]initWithFrame:NSMakeRect(10, 10, 100, 25)];
        [btn1 setTitle:String("Button 1").ToNSString()];
        [btn1 setButtonType:0];
        [btn1 setBezelStyle:1];
        [view addSubview:btn1];

        NSButton *btn2 = [[NSButton alloc]initWithFrame:NSMakeRect(10, 45, 100, 25)];
        [btn2 setTitle:String("Button 2").ToNSString()];
        [btn2 setButtonType:1];
        [btn2 setBezelStyle:1];
        [view addSubview:btn2];

        NSButton *btn3 = [[NSButton alloc]initWithFrame:NSMakeRect(10, 80, 100, 25)];
        [btn3 setTitle:String("Checkbox 1").ToNSString()];
        [btn3 setButtonType:3];
        [btn3 setBezelStyle:1];
        [view addSubview:btn3];

        [this->_window center];


/*
        //[this->_window update];
        // setNeedsDisplay:
        // setNeedsDisplayInRect:
        //
        // Avoid Forcing Synchronous Updates
        // When invalidating portions of your views, you should avoid using the display family of methods to force an immediate update. These methods cause the system to send a drawRect: message to the affected view (and potentially other views in the hierarchy) immediately rather than wait until the next regular update cycle. If there are several areas to update, this may result in a lot of extra work for your drawing code.
        // Instead, you should use the setNeedsDisplay: and setNeedsDisplayInRect: methods to mark areas as needing an update. When you call these methods, the system collects the rectangles you specify and coalesces them into a combined update region, which it then draws during the next update cycle.
        // If you are creating animated content, you should also be careful not to trigger visual updates more frequently than the screen refresh rate allows. Updating faster than the refresh rate results in your code drawing frames that are never seen by the user. In addition, updating faster than the refresh rate is not allowed in OS X v10.4 and later. If you try to update the screen faster than the refresh rate, the window server may block the offending thread until the next update cycle.
*/





        [this->_window display];
    
        [this->_window makeKeyWindow]; 
        [this->_window makeKeyAndOrderFront:app];
        

        //[app runModalForWindow:w1];
        [app run]; 
        //[w1 release];
    }

};
In PB it is more complicated IMO, as PB does not directly support OOP, and all modern Cocoa is completely object-oriented.

Re: NSPenel

Posted: Mon Dec 22, 2014 12:09 pm
by Wolfram
Du you have any idea why I cant use BindEvent(#PB_Event_LeftClick, @OnBtnClick() on the NSPanel?