Using DockPanelSuite, how do you get context menu for tab strip separate from document tab? - contextmenu

When using DockPanelSuite, is it possible to have a context menu for the tab strip that is different from the one for a document tab? For example, right click an empty space on the tab strip and get one context menu then right click a document tab and get a different context menu specific to the document.
I tried setting the ContextMenuStrip property of the DockPanel. I got a context menu for any empty space on the DockPanel control as well as the document tab strip when visible and all open document tabs. That's a good start but I really only wanted the context menu for the tab strip. Not the main control or any tabs.
I also followed along with the sample project to make a context menu for the document by setting the TabPageContextMenuStrip property of the DockContent form. I discovered that you get a document specific context menu by right clicking the document tab, but it also overrides the DockPanel's ContextMenuStrip. While that is useful, it's still not the desired result.
Edit:
Updating this post in case anyone else is interested in achieving the objective of the question.
After much source code analysis and testing, I concluded that the objective could not be achieved using the available public Properties, Methods, and Events. However, we can achieve the goal by using a bit of reflection.
Discoveries:
DockContent.ContextMenuStrip
This property does nothing for the DockPanel. It will provide a context menu in the client area of the document. However, for some reason, the RichTextBox control set to Fill in the provided sample blocks the context menu from popping up.
DockContent.TabPageContextMenuStrip
This property causes the associated ContextMenuStrip to display when the document is active. However, it displays when you right click anywhere on the tab strip, not just when you right click the document tab.
Solution:
First, add a public property to the DockContent form which will contain a reference to the context menu.
public ContextMenuStrip TabContextMenu { get { return contextMenuTabPage; } }
Next, add an event handler in the MDI main form for the DockPanel.ActiveDocmentChanged event. This will be used to add an event handler to the tab strip after it’s been created.
this.dockPanel.ActiveDocumentChanged += new System.EventHandler(this.dockPanel_ActiveDocumentChanged);
private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
{
// Hook into the document pane tabstrip mouse up event
// if we haven't already.
if (dockPanel.ActiveDocumentPane != null
&& dockPanel.ActiveDocumentPane.TabStripControl != null
&& dockPanel.ActiveDocumentPane.TabStripControl.Tag == null)
{
dockPanel.ActiveDocumentPane.TabStripControl.Tag = "MouseUp Hooked";
dockPanel.ActiveDocumentPane.TabStripControl.MouseUp +=
TabStripControl_MouseUp;
}
}
Finally, add the event handler for the TabStripControl.
private void TabStripControl_MouseUp(object sender, MouseEventArgs e)
{
// Capture right click action
if (e.Button == MouseButtons.Right)
{
ContextMenuStrip menu = contextMenuDocumentPane;
Point screenPos = Cursor.Position;
Point tabstripsPos = dockPanel.ActiveDocumentPane
.TabStripControl.PointToClient(screenPos);
// Determine if cursor is over a tab
var tabstrip = dockPanel.ActiveDocumentPane.TabStripControl;
var tabs = tabstrip.GetType()
.GetProperty("Tabs", BindingFlags.Instance |
BindingFlags.NonPublic).GetValue(tabstrip);
foreach (var tab in (IEnumerable)tabs)
{
var bounds = tab.GetType()
.GetProperty("Rectangle")
.GetValue(tab);
if (((Rectangle)bounds).Contains(tabstripsPos))
{
// Display context menu for this document tab
var document = tab.GetType()
.GetProperty("Content")
.GetValue(tab);
menu = ((ContentWindow)document).TabContextMenu;
}
}
// Show appropriate context menu
menu.Show(screenPos);
}
}

Related

Set cursor position of the editor control exactly where user tapped in Xamarin.forms

I am working in Xamarin.forms project. I want to set the cursor position of the Editor control exactly where the user tapped. I want to achieve this specifically in IOS (better to have a solution in Android too). I have gone through a couple of articles where they suggested using a custom renderer but I don't know how. I have gone through the following articles
https://social.msdn.microsoft.com/Forums/en-US/5bf7c17c-51c2-4e9e-bc09-73e9a5512fc3/how-to-change-the-cursor-position-of-entry-or-editor-programmatically?forum=xamarinforms
Set CursorPosition in Editor Xamarin Forms
Based on the above link, I have made a custom renderer of the Editor control. The code inside OnElementPropertyChanged in custom render keeps my cursor on the starting position of the editor control but I don't want this. The cursor position should change where the user tapped. we need to update the code inside the renderer according to my use-case.
public class CustomEditor : Editor
{
}
public class CustomEditorRenderer : EditorRenderer
{
public CustomEditorRenderer() { }
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Control != null)
{
// just change this statement to the one that works.
Control.SelectedTextRange = Control.GetTextRange(fromPosition: Control.BeginningOfDocument, toPosition: Control.BeginningOfDocument);
}
}
}
I have to use Editor control, not Entry control because I want to enter text in multiple lines. Editor control doesn't have a CursorPosition property like Entry control.
Can anyone suggest a better way through a custom renderer or via utilizing TextChanged, Focused event?
You can change your Renderer code to change the cursor position:
//Change the cursor position to the fifth character
var test = Control.GetPosition(Control.BeginningOfDocument, 5);
Control.SelectedTextRange = Control.GetTextRange(test, test);
If you want to change the cursor to the user's clicked position, you need to get the user's clicked position and convert it to the corresponding index value. For getting the user's click position, you can refer to the documentation:Walkthrough: Using Touch in Xamarin.iOS

Tab to Window or Vice Versa in Firefox AddOn

In a Firefox AddOn, is there a way to get a window object from a tab object? Or vice versa? For instance, if I get a TabClose event, is there a way to get the associated window object?
Yes in TabClose the event argument holds a lot of useful stuff:
function tabclosee(e) {
console.error('TabClose, e:', e);
}
gBrowser.tabContainer.addEventListener("TabAttrModified", tabclosee, false);
So in this image we see that e.view is the DOMWindow (xul window/chrome window). The target is the tab element, in the close situation the HTMLWindow was destoryed so e.target.linkedBrowser will be null, but in TabSelect it won't be null and you can access the html window like e.target.linkedBrowser.contentWindow
If you want window from tab object you can do this too: e.target.ownerDocument.defaultView, this is the same as doing e.view above.
From window you can access all tabs like this:
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var t=0; t<tabs.length; t++) {
var tab = tabs[t];
var tab_linkedBrowser = tab.linkedBrowser;
var tab_htmlWin = tab.linkedBrowser.contentWindow;
}
}

Approach for designing View in vaadin 7

I am newbie to vaadin. I have to develop PoC on vaadin. Service layer is already written using spring. As a part of Poc I have to develop a screen below.
When request comes to my UI class, it will call my View using navigator. This view consists of one tabsheet and each tab have its own functionality and depends on other tab values too. First tab is search tab. It displays all the records came from db in the tab content area(Table/Grid addon. I dont know what to use). Each record have access to other two tabs. The other two tabs has fields to map each record's property. As of now, i have taken dummy data to display.
I wrote the view like this . But I am confused weather this approach is correct or not.
#VaadinView(UserView.NAME)
public class UserView extends VerticalLayout implements View {
public static final String NAME = "user";
public UserView(){
// For Tabs
TabSheet tabs = new TabSheet();
// first tab component
VerticalLayout layout = new VerticalLayout();
// for search fields
HorizontalLayout searchArea = new HorizontalLayout();
FormLayout searchAreaName = new FormLayout();
TextField name = new TextField("name");
FormLayout searchAreaEmail = new FormLayout();
TextField email = new TextField("email");
searchAreaName.addComponent(name);
searchAreaEmail.addComponent(email);
searchArea.addComponent(searchAreaName);
searchArea.addComponent(searchAreaEmail);
// for search table
BeanContainer<String, test.User> users = new BeanContainer<String, User>(
User.class);
users.setBeanIdProperty("userId");
users.addBean(new User("sudheer", "sudheer#kewil.com", "1"));
users.addBean(new User("sridhar", "sridhar#kewil.com", "2"));
users.addBean(new User("ranga", "ranga#kewil.com", "3"));
Table table = new Table("", users);
table.setSizeFull();
table.setPageLength(6);
layout.addComponent(searchArea);
layout.addComponent(table);
Tab tabOne = tabs.addTab(layout, "User Search", null);
// second tab component
VerticalLayout userLayout = new VerticalLayout();
userLayout.addComponent(new TextField("user name"));
userLayout.addComponent(new TextField("email"));
tabs.addTab(userLayout, "main details", null);
// tab change event
addComponent(tabs);
tabs.setHeight("50%");
tabs.setWidth("50%");
setComponentAlignment(tabs, Alignment.MIDDLE_CENTER);
}
#Override
public void enter(ViewChangeEvent event) {
}
}
I haven't implemented pagination also. Before going forward, I would like to know any other best approaches to go ahead.
Any suggestions would help me very much. Thanks in advance.
Anybody.. please help me out. I am going blindly with my appproach
Here is what I do in such cases:
Use the Blackboard event bus to fire events. These events carry a payload that essentially is the id of the record clicked/selected.
The other tabs or views are registered as a listener of this event. When the event is fired, the listeners extract the record/entity id from the payload, fetch the entity object from the back-end, and display it accordingly.
This approach ensures loosely-coupled components.
I hope it helps.

how to add standard textbox command to jqgrid context menu

If context menu is added to jqGrid using Custom values to Context Menu Items in JQgrid and text filed inline editing is used, textbox standard context menu is not available, it is replace with jqGrid context menu.
How to add standard textbox context menu commands ( Undo, Cut, Copy, Paste, Delete, Select all ) to jqGrid conext menu or how to show standard context menu for textbox inline editing?
Update
On inline edit, if standard menu is opened by right clicking on yellow background or in autocomplete box and after that standard browser context menu is opened, custom menu is not closed, two menus appear.
How to fix this ?
It's not easy to implement in context menu commands like "Copy", "Paste", ... so I decide to modify my demo from the answer on your previous question. In the new demo the context menu appears only if the page contains no selected text.
The first problem is that the original code of the jquery.contextmenu.js contains the following code fragment:
$(this).bind('contextmenu', function(e) {
// Check if onContextMenu() defined
var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;
if (bShowContext) display(index, this, e, options);
return false;
});
So the contextmenu handler return always false and prevent creating of the standard context menu. I fix the code to the following (you can download full modified code here):
$(this).bind('contextmenu', function(e) {
// Check if onContextMenu() defined
var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;
currentTarget = e.target;
if (bShowContext) {
display(index, this, e, options);
return false;
}
});
The code of createContexMenuFromNavigatorButtons functions described here I modified
onContextMenu: function (e) {
var rowId = $(e.target).closest("tr.jqgrow").attr("id"), p = grid[0].p, i,
lastSelId;
if (rowId && getSelectedText() === '') {
...
return true;
} else {
return false; // no contex menu
}
}
to use getSelectedText() and to create the context menu only if no text is selected. As the result you will be see your custom context menu only if no text is selected and see the standard context menu (which depend on web browser) if the text selection exist:
UPDATED: I modified my bug report about jquery.contextmenu.js with additional information based on the answer. I hope that the changes will be soon in the main code of jquery.contextmenu.js included in the plugins subdirectory.
UPDATED 2: How you can see here all the fixes are already in the main code of jqGrid on the github and in included in the jqGrid 4.3.
UPDATED 3: If you want to have the standard context menu for all enabled <input type="text" ...>, <input type="textarea" ...> and <textarea ...> elements you should just modify a little the code inside of onContextMenu callback. For example
onContextMenu: function (e) {
var p = grid[0].p, i, lastSelId,
$target = $(e.target),
rowId = $target.closest("tr.jqgrow").attr("id"),
isInput = $target.is(':text:enabled') ||
$target.is('input[type=textarea]:enabled') ||
$target.is('textarea:enabled');
if (rowId && !isInput && getSelectedText() === '') {
...
see one more demo where inline editing will be activate by double-click.

Silverlight - ListBox with a button dynamically bound - how do I get the original list item data?

I've got a ListBox, within it I have a custom DataTemplate that builds a button. Each button represents a selection the user can perform.
When the button is clicked, is there anyway I can retrieve the original data record for that bound item? In standard C#, I can create a button and use CommandArgument to pass an ID to an event. Is there something similar in Silverlight?
Thanks
private void RemoveMember_Click(object sender, RoutedEventArgs e)
{
var employee = ((Button)sender).DataContext as Employee;
if(employee == null)
return;
_employeeList.Items.Remove(employee);
}

Resources