NSMenu with 2 standard + variable number of NSMenuItems - objective-c

I have an NSMenu with 2 default items (at the top of it).
Then the rest of the menu will be populated.
What I want is to "save" the state of the initial menu (with the two items in it), and add items to that (original) menu; and not just keep adding and adding.
So, if I have to add other items, those will have to be added in the initial menu.
Example :
Menu At the beginning : A B |
Menu After User does This : A B | C D E
Menu After User does That : A B | G H I J K
etc
How should I go about that? (I tried "saving" the initial menu, and then "copying" that to the current menu, so that I could add items on top of it, but it didn't work... :-S)
[DOC_UI setCurrentMenu:[[DOC_UI originalMenu] copy]];
// I'm adding the items here
for (NSMenuItem* mi in [[DOC_UI currentMenu] itemArray])
NSLog(#"orig :: mi : %#",[mi title]);
/* The weird thing is that the items ARE NSlogged, but the change is NOT reflected. */
/* (When I was just adding to the existing items, the items did show up...) */

If you're talking about menu items of a menu, you can remove all but the first 2 items in a loop when you want to go back to your original menu. If you have a menu with 2 default items called userMenu, just do this:
-(void)removeMenuItems {
for (NSInteger i=self.userMenu.itemArray.count - 1; i>1; i--) {
[self.userMenu removeItemAtIndex:i];
}
}

Related

RecyclerView custom LayoutManager remove unwanted views

I have a custom LayoutManager (inherited from LinearLayoutManager) that needs to calculate the item width of each child and remove all children from RecyclerView that has no space for them to appear.
Sample code (edited V2):
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
super.onLayoutChildren(recycler, state)
// skip if orientation is vertical, for now we only horizontal custom menu
if (orientation == RecyclerView.VERTICAL) return
// skip if adapter has no items
if (itemCount == 0) return
var totalItemWidth = 0
var totalItemsCanFit = 0
// calculate menu item width and figure out how many items can fit in the screen
for (i in 0 until childCount) {
getChildAt(i)?.let { childView ->
totalItemWidth += getDecoratedMeasuredWidth(childView)
}
if (screenWidth > totalItemWidth) {
totalItemsCanFit++
}
}
// if all items can fit, do nothing and show the whole menu
if (childCount > totalItemsCanFit) {
// remove child views that have no space on screen
for (i in childCount - 1 downTo totalItemsCanFit) {
removeAndRecycleViewAt(i, recycler)
}
}
}
I have 2 questions:
Is the sample code above the correct way to approach this problem?
How can I add a 3-dot icon at the end after seeing that not all items could fit?
EDIT:
To clarify, what I am trying to achieve is a popup menu backed by a RecyclerView. The menu has no item limit, instead it should calculate each item width and remove all items that have no space. Also, add a 3-dot menu item as a more option at the end.
Regarding your first question:
See if addDisappearingView(View child) could help you,
according to the documentation:
To be called only during onLayoutChildren(Recycler, State) to add a
view to the layout that is known to be going away, either because it
has been removed or because it is actually not in the visible portion
of the container but is being laid out in order to inform RecyclerView
in how to animate the item out of view.
As for the second question - you simply need to implement a 'load more' feature to your recyclerView. How you'll implement this is up to your needs/design (if you want a button or auto-scroll...).
There are many tutorials for that, for example: https://androidride.com/android-recyclerview-load-more-on-scroll-example/ .

replacement for tabbar selected index

I have an old app where I have 5 tabs. Each tab have list of ads & there is details. Also each tab have respective add ad. Design for all 5 tabs is same except some changes, so I decided to use 1 screen only for all 5 tabs.
Now what I am doing is while add ad, I am checking which tab I am and based on tab bar index, I am showing hiding fields. Same is applicable for details screen also. Sample code is as shown below.
if (self.tabBarController.selectedIndex==0) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==1) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==2) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==3) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==4) {
field1.hidden = YES;
}
Now I have around 15 fields for each form so I write this code for all fields.
What I noticed that client change the tab bar position continuously so I was looking for efficient way of doing it.
Right now what I do is at all places manually change index positions by doing Search-Replace, however I dont like this.
I was looking for a way where instead of selectedIndex, I was looking for someconstant value that I will assign to tab item of tab bar, so my code will change as below
if (self.tabBarController.selectedIndex==adType_News) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==adType_Occasions) {
.
.
And so on...
This way, I only need to change in the storyboard and code level will not have any changes.
Is there way where I can achieve this?
Main Issue
As client ask to change tab bar completely, I need to make changes of selectedIndex changes at all places which I don't like and feel more in-efficient way. So I was looking for a way where I will make change in storyboard only and coding level there won't be any change.
The main issue for me is changing selectedIndex in all files which make more error.
I think I understand the question to mean that the code is full of number literals, referring to the selected index of the tabbar, and the business requirements about the ordering of items are shifting. Fix by changing the literals to something symbolic that can be controlled centrally:
// in a new file, indexes.h
#define INDEXA (0)
#define INDEXB (1)
#define INDEXC (2)
// wherever existing code refers to the tab selection
#import "indexes.h"
// in the code, for example if selectedIndex == 2, change to
if (self.tabBarController.selectedIndex==INDEXC) {
// ...

Select a tab bar item depending on its tag number

I have an app which has 7 tab bar items. At some point I want to programmatically click 1 of the tab bar items . Each tab bar item has a unique tag number. I want to do something like this:
[self.tabBarController setSelectedTag:9]; Or get the index of a tab bar item whose tag number is 9 so that I can use it in [self.tabBarController setSelectedIndex:index]. I cannot find any solution. Can anyone please help me.
Thanks in advance.
Just iterate over the view controllers to find the one with the tag you require, then select it. Something like this ...
// find the view controller
UIViewController* viewControllerToSelect;
for(UIViewController* vc in self.tabController.viewControllers) {
if (vc.tag == tagToFind) {
viewControllerToSelect = vc;
break;
}
}
// select it
self.tabController.selectedViewController = viewControllerToSelect;
There are more elegant ways to search, using predicates - but the above should do the trick.

How to invoke Context Menu for empty selection?

My Tree structure looks like this, containing three classes Index,Key,Value
Index1
|
-- Key1
|
-- Value1
Index2
|
-- Key2
|
-- Value2
I'm creating a context menu for an index entry which should have three actions(newKeyAction , newValueAction, removeAction)
and by right clicking on the empty space addAction should be popped up.
This is the code responsible:
protected void fillContextMenu( IMenuManager manager )
{
ITreeSelection mySelection = (ITreeSelection) viewer.getSelection();
if(mySelection.size() == 1)
{
if(mySelection.getFirstElement() instanceof Index)
{
manager.add( newKeyAction );
manager.add( newValueAction );
manager.add( removeAction );
}
}
else
{
manager.add( addAction);
}
}
Everything works fine, but the addAction is being invoked only once when the treeViewer is empty, and there after by right clicking on the empty space, node last selected in the tree is being selected and its respective actions are displayed.
Please let me know where i'm going wrong .
there after by right clicking on the empty space, node last selected in the tree is being selected and its respective actions are displayed.
That's your problem and you can't do anything about it. It's just not possible to clear the selection like this. You should find another way to make addAction available.

How do I determine the page number for the tab I just clicked on in gtk#?

I have a GTK notebook with multiple tabs. Each tab label is a composite container containing, among other things, a button I want to use to close the tab. The button has a handler for the "clicked" signal.
When the signal is called, I get the button widget and "EventArgs" as a parameter.
I need to determine the page number based on the button widget, but myNotebook.PageNum(buttonWidget) always returns -1. I've even tried buttonWidget.Parent which is the HBox which contains the widget.
Any ideas on what I can do or what I am doing wrong?
One easy work around is to pass the page number to your button's Clicked event as you construct the buttons.
for (int page = 0; page < n; page++){
int the_page = page;
NotebookPage p = new NotebookPage ();
...
Button b = new Button ("Close page {0}", the_page);
b.Clicked += delegate {
Console.WriteLine ("Page={0}", the_page);
};
}
The "the_page" is important, as it is a new variable that will be captured by the delegate.