How to Mimic Finder NSPredicateEditor leftExpression list - objective-c

I would like to mimic the Finder's predicatesList. Especially the LeftExpressions popup with its "other" (in German: "Andere...") menu entry and like to popup a NSSheet with a user selectable list of search predicates.
My approach was to create some NSPredicateEditorRowTemplates and one last custom rowTemplate with a leftExpression named "other...".
Then I override the templateViews method and added a separatorItem:
-(NSArray *)templateViews{
NSMutableArray * views = [[super templateViews] mutableCopy];
// I tried already to add here my custom menu entry, but if I add more templates my custom entry (and the separator line) is not fixed at the last index.
if (!isCustomMenuItemAdded) {
NSPopUpButton *leftButton = views[0];
// Add a menu separator
[[leftButton menu]insertItem:[NSMenuItem separatorItem] atIndex:[leftButton menu].itemArray.count-1];
}
return views;
}
My custom predicateEditor is now shown correctly, But if I click on the last menu item 'Other.." the dummy NSPredicateRowTemplate shows up.
I tried to override the -(id)copy method in my rowTemplate class to suppress the new line but that feels strange to me.
-(id)copy{
return nil; // OK, now there is no new row, but this throws an internal exception
}
My question is:
Is there a better way to add a custom menu entry in the left expressions popupButton?
and
How can I suppress that a new predicateTemplateRow is shown in the PredicateEditor?

Related

Modifying column header names in Master-Detail grid in Devexpress

I have a Master-Detail set up with 2 grids. On the master grid, I have the ShowOnlyPredefinedDetails option set to false.
This means that I see a little + sign that allows me to expand the details of the detail grid (in the master grid). I would like to rename
some columns in that section as well as hide certain columns. I'm using VB.NET How do I go about this. See image.
You can accomplish this by using the grid control ViewRegistered event, from there you can modify the columns in that grid view that have columns within them that you want to modify, rename, or remove. Here is an example, I hope that it helps:
private void myGridControl_ViewRegistered(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e)
{
if (e != null)
{
if (e.View != null)
{
//Inside of this statement you can adjust, add, and modify all of the columns inside of that grid that appears when you click on the +
(e.View as GridView).Columns["myHiddenColumn"].Visible = false;
(e.View as GridView).Columns.Add(new GridColumn() { Name = "AddColumn", Caption = "Name To Display", Visible = true, FieldName = "DataField"});
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowEdit = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowFocus = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.ReadOnly = true;
}
}
}
I think all you need to do is create a second grid view for your details. If you haven't already done this, do the following:
In your grid designer, click "Retrieve Details" if you have not already done so. This will cause the designer to recognize that you have a second level in your bound object:
Once you see the second layer, now you need a new grid view for it. Click on "Click here to change view" and select "Create a new view" and pick "GridView."
Now you will see both grid views from the designer, and clicking on one or the other will change the context of the menus to the left:
For example, if you have gridView2 selected, when you click on the "Layout" menu, it will show the current layout for your detail grid rather than the master grid. From here, you can remove or add columns as you see fit. Likewise, from the "Columns" menu you will see the new columns (you may have to add them to the view by dragging them over), and you can change the Caption property to change the text of the title.
I suggest you use the Data Annotation attributes with properties of your data-classes to declare how you data should be displayed in GridControl:
To skip column generation for the specific property you can mark this property with the <DisplayAttribute(AutoGenerateField := false)> declaration.
To prevent column from displaying you can mark this property with the <DisplayAttribute(Order := -1)> declaration. Later, user can show this column via Column Chooser UI.
To specify the column caption use the <DisplayAttribute(Name := "YOUR CAPTION")> declaration.
You can also control filtering/editing/formatting and validation capabilities.
Related Links:
Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes
Video Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes

NSPredicateEditor is clearing the value of its NSTextField

I'm using NSPredicateEditor in my project. One of my rows has 2 popup buttons and a text field on the right. If I have something typed in the text field, when I select a different menu item from either of the popup buttons then the text in the text field is deleted. That seems to be the default behavior and I don't want that text deleted. I've tried everything I can think of and can't seem to handle this. Any ideas how to change this behavior?
You could save the data by using NSUserDefault it will save and load the data (It won't delete your data unless the user does).
Access the text fields via the row template's templateViews property.
This allows you to get the custom values that have been entered into the textfield. Save the value when it changes.
class YourCustomRowTemplate : NSPredicateEditorRowTemplate {
func printTextFieldValues() {
let templateViews = super.templateViews
for view in templateViews {
if let textField = view as? NSTextField {
let text = textField.stringValue
print("Text in the texfield is: \(text)")
}
}
}
}
You can set the values the same way, by subclassing NSPredicateEditorRowTemplate and overriding the templateViews method.

How to show a Safari Extension popover programmatically

I'm trying to write a Safari extension that consists of a button on the main toolbar with a popover tied to it, and a contextual menu item. The basic feel is modeled after the feel of the 1Password extension.
One of the jobs of the popover is to allow a person to log in. I'm also conditionally changing the action of the contextual menu item, and if a who person isn't logged in clicks the menu item I would like to show the popover allowing them to log in, but I can't find a way to do this in the developer guides.
How do I "show" a popover?
If you only have one toolbar item and one popover (and never plan to add more), then it's just one line. Assuming you've already assigned the popover to the toolbar item in Extension Builder, you can just use:
safari.extension.toolbarItems[0].showPopover();
But if you have more than one popover and (potentially) more than one toolbar item, here's a generalized function to open a popover, specified by its identifier, under the specified toolbar item in the active browser window:
function showPopover(popoverId, toolbarItemId) {
var toolbarItem = safari.extension.toolbarItems.filter(function (tbi) {
return tbi.identifier == toolbarItemId && tbi.browserWindow == safari.application.activeBrowserWindow;
})[0];
var popover = safari.extension.popovers.filter(function (po) {
return po.identifier == popoverId;
})[0];
toolbarItem.popover = popover;
toolbarItem.showPopover();
}

NSMenu --> Adding SubMenu --> receive select event

I need to create a Menu for a selected row of a table,
I am able to create by overriding
-(NSMenu*)menuForEvent:(NSEvent*)evt
Method, of a table, This particular Menu has two sub-menu, i am able to make the Sub-Menu
but facing Following Problem
1 -- To Add a Sub-Menu in a MenuItem, i need to get Sub-Menu from a different class/Interface, i am calling following method
pSubMenu = [CommonUIUtil GetCommonUIMenu:pSubMenu
ActionId:self
Selector:#selector(MyMenuAction)];
Where prototype of this function is as follow
+(NSMenu *)GetCommonStatusMenu:(NSMenu *)pMenu ActionId:(NSObject*)aDelegate Selector:(SEL)selector
Implementation as below,
// pStrArray is Array of String to have the Menu Title
for(int idx =0;idx<[pStrArray count];idx++)
{
pTempStr = [pStrArray objectAtIndex:idx];
pImage = [CommUIController CommonGetImage:[CommonUIUtil GetImageByStatus:pTempStr]];
[pImage setSize:NSMakeSize(20,20)];
pMenuItem =[[NSMenuItem alloc]init];
[pMenuItem setTitle:pTempStr];
// this should set the selector
[pMenuItem setAction:selector];
// Setting the target
[pMenuItem setTarget:aDelegate];
[pMenuItem setImage:pImage];
[pMenuItem setEnabled:YES];
[pMenu addItem:pMenuItem];
[pMenuItem release];
}
return pMenu;
I am able to see the Image, String on this Sub Menu, but the problem i am facing is this menu is not at all Enable, can anyone guide me , where i am making the mistake,
This function will return the Menu and Menu i will add as below,
pMenuItem = [pCTTableMenu itemWithTitle:#"Status"];
//status menu is the menu returned from the above function,
[pMainMenu setSubmenu:pStatusMenu forItem:pMenuItem];
Thanks in Advance :)
looks like, i am not passing the selector method properly, in fact i don't know how to pass function pointer in Cocoa, probably i am mixing Cocoa/Objective C and Normal C both :), corrected, it, in the method just creating the view and in the main class/interface assigning target and action

Something like .NET's "tag" property for Interface Builder

I'm currently struggling to use UI elements in Interface Builder. I keep trying to do things "in the .NET way."
I have several buttons that all map down their TOUCH event to the SAME FUNCTION:
-(IBAction) onTouch:(id) sender
{
// do something with touch, DEPENDING ON WHAT BUTTON WAS PUSHED
// I want to do something like
if( sender.tag == "something" )
{
//...doesn't work on apple, of course..
}
}
I want to uniquely identify each BUTTON USING SOMETHING like the TAG property in .NET. I tried using the INTERFACE BUILDER "NAME" field that is on the "Identity" panel of interface builder, but I don't know how to access that field programmatically.
-(IBAction) onTouch:(id) sender
{
// do something with touch, DEPENDING ON WHAT BUTTON WAS PUSHED
// I want to do something like
if( sender.InterfaceBuilderName == "something" )
{
//...doesn't work..
}
}
So, WHAT / IS THERE a way to uniquely identify a UI element (such as a button) OTHER THAN doing something like
-(IBAction) onTouch:(id) sender
{
// look at
[sender currentTitle]
}
The reason that's bad is because if the text on the button changes for some cosmetic reason you break the whole app, right
The last solution I can think of is write seperate functions for each button's touch event but I really want to know if it is possible to uniquely identify a button by something similar to .Net's TAG property.
In the iPhone SDK all UIView objects have a property also called tag which is an integer value and can basically be used to do what you are intending.
I usually define a constant for the tag values I'm going to use for a specific purpose.
You can access the tag on the button object:
myButton.tag = MYBUTTON_TAG_CONSTANT
// button tag constant
#define MYBUTTON_TAG_CONSTANT 1
For buttons, there is a Tag entry in the View section (click on your button, select Attributes Inspector from the Tools menu). You can then use this integer value in your code.
Here is a link that may help as well:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/25582-using-tags-interface-builder.html
UIView's tag property is accessible from Interface Builder. Unlike .NET, it's an integer rather than a string.