Selection event listener on graph - jgrapht

I would like to implement a selection event listener on a graph to change the style of the selected vertices.
I have tried the following:
String[] events =
{mxEvent.ADD, mxEvent.ADD_CELLS, mxEvent.ADD_OVERLAY, mxEvent.AFTER_PAINT,
mxEvent.ALIGN_CELLS, mxEvent.BEFORE_PAINT, mxEvent.BEFORE_UNDO,
mxEvent.BEGIN_UPDATE, mxEvent.CELL_CONNECTED, mxEvent.CELLS_ADDED,
mxEvent.CELLS_FOLDED, mxEvent.CELLS_MOVED, mxEvent.CELLS_ORDERED,
mxEvent.CELLS_REMOVED, mxEvent.CELLS_RESIZED, mxEvent.CELLS_TOGGLED,
mxEvent.CHANGE, mxEvent.CLEAR, mxEvent.CONNECT, mxEvent.CONNECT_CELL,
mxEvent.CONTINUE, mxEvent.DONE, mxEvent.DOWN, mxEvent.END_UPDATE,
mxEvent.EXECUTE, mxEvent.FIRED, mxEvent.FLIP_EDGE, mxEvent.FOLD_CELLS,
mxEvent.GROUP_CELLS, mxEvent.INSERT, mxEvent.LABEL_CHANGED,
mxEvent.LAYOUT_CELLS, mxEvent.MARK, mxEvent.MOVE_CELLS, mxEvent.NOTIFY,
mxEvent.ORDER_CELLS, mxEvent.PAINT, mxEvent.REDO, mxEvent.REMOVE_CELLS,
mxEvent.REMOVE_CELLS_FROM_PARENT, mxEvent.REMOVE_OVERLAY, mxEvent.REPAINT,
mxEvent.RESIZE_CELLS, mxEvent.ROOT, mxEvent.SCALE,
mxEvent.SCALE_AND_TRANSLATE, mxEvent.SELECT, mxEvent.SPLIT_EDGE,
mxEvent.START, mxEvent.START_EDITING, mxEvent.STOP, mxEvent.TOGGLE_CELLS,
mxEvent.TRANSLATE, mxEvent.UNDO, mxEvent.UNGROUP_CELLS, mxEvent.UP,
mxEvent.UPDATE_CELL_SIZE};
for (String event : events) {
jgxAdapter.addListener(event, new mxEventSource.mxIEventListener() {
#Override
public void invoke(Object sender, mxEventObject evt) {
System.out.println(evt.getName());
}
});
}
but the only events that print in the console are:
cellsAdded, addCells, cellsResized, updateCellSize, repaint and cellConnected
How do I catch the selection event with jgraphx or jgrapht ?

The selection event is mxEvent.CHANGE and should be listened to via mxGraphSelectionModel.
jgxAdapter.getSelectionModel().addListener(mxEvent.CHANGE, new mxIEventListener() {
#Override
public void invoke(Object sender, mxEventObject evt) {
mxGraphSelectionModel sm = (mxGraphSelectionModel) sender;
mxCell cell = (mxCell) sm.getCell();
if (cell != null && cell.isVertex()) {
//do something
}
}
});

Related

Programatically change state of GridViewCheckBoxColumn row with updating binding source for Telerik's GridView

I'm making a custom behavior for Telerik's RadGridView.
When this behavior is attached and its PropertyName is set to same property as specified by
DataMemberBinding value of some of the GridViewCheckBoxColumn of the grid, then toggling the checkbox in that column will apply same checkbox state to all selected rows (but only to the same column).
That happens in the ApplyToAllSelected method, namely in gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked); line. The visuals are working as expected, and all checkbox values are updated on screen.
The Problem is that the binding source is not updated for those rows. Only for the one where click happened. GridViewCheckBox.IsChecked dependency property does not seem to be bound directly to the datacontext's property, so gvcb.GetBindingExpression(GridViewCheckBox.IsChecked) returns null.
The Question: how to update source after setting checkbox state?
public sealed class CheckAllSelectedBehavior : Behavior<RadGridView>
{
public event EventHandler Toggled;
public string PropertyName { get; set; }
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.PreparingCellForEdit += this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded += this.AssociatedObject_CellEditEnded;
}
protected override void OnDetaching()
{
this.AssociatedObject.PreparingCellForEdit -= this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded -= this.AssociatedObject_CellEditEnded;
base.OnDetaching();
}
private void AssociatedObject_CellEditEnded(object sender, GridViewCellEditEndedEventArgs e)
{
if (e.Cell.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked -= this.Cb_Checked;
cb.Unchecked -= this.Cb_Unchecked;
}
}
private void AssociatedObject_PreparedCellForEdit(object sender, GridViewPreparingCellForEditEventArgs e)
{
if (e.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked += this.Cb_Checked;
cb.Unchecked += this.Cb_Unchecked;
}
}
private void Cb_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(false);
}
private void Cb_Checked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(true);
}
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
var row = this.AssociatedObject.GetRowForItem(item);
var cell = row.GetCellFromPropertyName(this.PropertyName);
if (cell.Content is GridViewCheckBox gvcb)
{
gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked);
}
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
}
Using reflection to set the value on viewmodel property seems to work. Modify the ApplyToAllSelected method like follows:
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
this.SetProperty(item, isChecked);
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
private void SetProperty(object target, bool isChecked)
{
var prop = target.GetType().GetProperty(
this.PropertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
prop.SetValue(target, isChecked);
}

WebKit.NET C# Custom Context Menu

I am implementing a Webkit Browser control in my windows app.
I need to use a custom context menu (right click) that only has copy/cut/paste as its options regardless of what element is right clicked. I need kind of a step-by-step as to how to implement it
Customizing the context menu for the WebKitBrowser supposes that you get a reference to the WebViewClass and then, setting a IWebUIDelegate for it by calling the setUIDelegate() method.
void MyWebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webView = this.GetWebView() as WebKit.Interop.WebViewClass;
webView.setUIDelegate(new MyWebUIDelegate(this));
}
In the IWebUIDelegate implementation you may intercept the contextMenuItemsForElement method and trigger the display of the context menu of the browser.
Here is a working sample:
public partial class Form1 : Form
{
MyWebBrowser webKitBrowser;
public Form1()
{
InitializeComponent();
webKitBrowser = new MyWebBrowser();
webKitBrowser.Dock = DockStyle.Fill;
this.Controls.Add(webKitBrowser);
webKitBrowser.Navigate("http://www.google.com");
}
}
class MyContextMenu : ContextMenu
{
public MyContextMenu()
{
var cutMenuItem = new MenuItem("Cut");
var copyMenuItem = new MenuItem("Copy");
var pasteMenuItem = new MenuItem("Paste");
cutMenuItem.Click += cutMenuItem_Click;
MenuItems.Add(cutMenuItem);
MenuItems.Add(copyMenuItem);
MenuItems.Add(pasteMenuItem);
}
void cutMenuItem_Click(object sender, EventArgs e)
{
//TODO: implement functionality
MessageBox.Show("Cut was selected");
}
}
class MyWebBrowser : WebKitBrowser
{
public event EventHandler ShowContextMenu = new EventHandler(OnFireShowContextMenu);
public MyWebBrowser()
{
DocumentCompleted += MyWebBrowser_DocumentCompleted;
var myContextMenu = new MyContextMenu();
ContextMenu = myContextMenu;
}
void MyWebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webView = this.GetWebView() as WebKit.Interop.WebViewClass;
webView.setUIDelegate(new MyWebUIDelegate(this));
}
public static void OnFireShowContextMenu(object sender, EventArgs e)
{
var webBrowser = (Control)sender;
var webView = (WebKit.Interop.WebViewClass)((MyWebBrowser)sender).GetWebView();
var originalPoint = webBrowser.PointToScreen(new Point(0, 0));
var currentPoint = new Point(Cursor.Position.X - originalPoint.X, Cursor.Position.Y - originalPoint.Y);
((WebKitBrowser)sender).ContextMenu.Show((Control)sender, currentPoint);
}
public void FireShowContextMenu()
{
this.ShowContextMenu(this, null);
}
}
class MyWebUIDelegate : IWebUIDelegate
{
private MyWebBrowser owner;
public MyWebUIDelegate(MyWebBrowser browser)
{
this.owner = browser;
}
//trigger the browser's FireShowContextMenu() method
public int contextMenuItemsForElement(WebView sender, CFDictionaryPropertyBag element, int defaultItemsHMenu)
{
owner.FireShowContextMenu();
return defaultItemsHMenu;
}
//return 1, true
public int hasCustomMenuImplementation()
{
return 1;
}
//the rest of the IWebUIDelegate interface implementation
}
For more insight, probably you would want to study some other customizations, such as open-webkit-sharp.

Disable panning when dragging a pushpin

I'm trying to prevent the WPF Bing Maps control from panning when the user is dragging a pushpin. What I do is that when the user selecting the pushpin with the MouseLeftButtonDown I'm, taking over the events from the map ViewChangeStart, ViewChangeOnFrame and set the e.Handled property to true.
What I was expecting is that if I set the property to true the events are canceled and panning is disabled. However the map is still panning.
Another approach what I tried is setting the property SupportedManipulations to None. Both options don't have the expected results.
Below is the code that I'm using for my DraggablePushpin
public class DraggablePushpin : Pushpin
{
private bool isDragging = false;
protected override void OnPreviewMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
var parentLayer = this.Parent as MapLayer;
if (parentLayer != null)
{
Map parentMap = parentLayer.Tag as Map;
if (parentMap != null)
{
parentMap.ViewChangeStart += parentMap_ViewChangeStart;
parentMap.MouseLeftButtonUp += parentMap_MouseLeftButtonUp;
parentMap.MouseMove += parentMap_MouseMove;
parentMap.SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.None;
}
}
this.isDragging = true;
base.OnPreviewMouseLeftButtonDown(e);
}
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
}
void parentMap_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
var map = sender as Map;
// Check if the user is currently dragging the Pushpin
if (this.isDragging)
{
// If so, the Move the Pushpin to where the Mouse is.
var mouseMapPosition = e.GetPosition(map);
var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition);
this.Location = mouseGeocode;
}
}
void parentMap_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
(sender as Map).SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.All;
}
protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
{
var parentLayer = this.Parent as MapLayer;
if (parentLayer != null)
{
Map parentMap = parentLayer.Tag as Map;
if (parentMap != null)
{
parentMap.SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.All;
}
}
}
void parentMap_ViewChangeStart(object sender, MapEventArgs e)
{
if (this.isDragging)
{
e.Handled = true;
}
}
}

Drag-select with ListBox

I have a simple implementation of a ListView in WPF that allows me to select multiple items in the list by holding the mouse button and dragging over the items. However, while holding the mouse button down, when I move the mouse outside the ListView, something strange happens with the selection. Ideally, I would just want the selection to remain the same, but instead it quickly cycles through all the selected items, leaving only the last item selected.
Here's the code, have any ideas?
public class MultiSelectListView : ListView
{
private bool m_isSelectionActive;
public bool IsSelectionActive
{
get { return m_isSelectionActive; }
}
protected override DependencyObject GetContainerForItemOverride()
{
return new MultiSelectListViewItem(this);
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
m_isSelectionActive = true;
}
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
m_isSelectionActive = false;
}
}
public class MultiSelectListViewItem : ListViewItem
{
private readonly MultiSelectListView m_parent;
public MultiSelectListViewItem(MultiSelectListView parent)
{
m_parent = parent;
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
if (m_parent.IsSelectionActive)
IsSelected = true;
}
}
The funkiness you are experiencing happens when the mouse "drag" goes above the top of the list or below the bottom of the list. I think the behavior you set up will only work well if the selection mode is Multiple. The modifications to the MultiSelectListView below set the default selection mode to Multiple and assumes the user wants to start another selection with a left mouse click. You will still experience funkiness if the SelectionMode is set to Extended or Single in the XAML.
public class MultiSelectListView : ListView
{
private bool m_isSelectionActive;
public bool IsSelectionActive
{
get
{
return m_isSelectionActive;
}
}
protected override DependencyObject GetContainerForItemOverride()
{
return new MultiSelectListViewItem(this);
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (SelectionMode != SelectionMode.Single)
{
SelectedItems.Clear();
}
m_isSelectionActive = true;
}
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
m_isSelectionActive = false;
}
public MultiSelectListView() : base()
{
SelectionMode = SelectionMode.Multiple;
}
}

Default Text in silverlight search text box

I need a feature in silverlight text box, simillar functionality as in Ask Question "Title" textbox in stalkoverflow. When there's no text in textbox then it should display "Search". When user clicked on the textbox then textbox text should be empty and in textbox lost focus if the text is empty then show "Search". I wrote the following code, but is there any code which handles all possible conditions?
private void txtAvailable_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
txtAvailable.Text = "";
}
private void txtAvailable_LostFocus(object sender, RoutedEventArgs e)
{
if (txtAvailable.Text.Trim() == "")
txtAvailable.Text = "Search";
}
You could use the Textbox GotFocus and LostFocus events - they should be generic enough to cover off all of your potentials..
The specialness comes when you want to search on every keystroke - you have to enable and disable searching on those events.
private bool IsBusy
{
get;
set;
}
private bool CanSearch
{
get;
set;
}
public Constructor()
{
InitializeComponent();
this.IsBusy = false;
txtSearch.GotFocus += new RoutedEventHandler( txtSearch_GotFocus );
txtSearch.LostFocus += new RoutedEventHandler( txtSearch_LostFocus );
txtSearch.KeyUp += new System.Windows.Input.KeyEventHandler( txtSearch_KeyUp );
txtSearch.Text = "Search »";
}
private void txtSearch_LostFocus( object sender, RoutedEventArgs e )
{
if( string.IsNullOrEmpty( txtSearch.Text ) )
{
CanSearch = false;
txtSearch.Text = "Search »";
}
}
private void txtSearch_GotFocus( object sender, RoutedEventArgs e )
{
txtSearch.Text = string.Empty;
CanSearch = true;
}
private void OnFilterCommand()
{
try
{
if( !IsBusy && CanSearch )
{
AppMessages.FilterAssetMessage.Send( txtSearch.Text );
}
}
catch( Exception ex )
{
// Notify user if there is any error
AppMessages.RaiseErrorMessage.Send( ex );
}
}
private void txtSearch_KeyUp( object sender, System.Windows.Input.KeyEventArgs e )
{
OnFilterCommand();
}
If you're familiar with WPF and the differences between WPF and Silverlight, take a look at the WatermarkTextBox in the extended WPF toolkit:
http://wpftoolkit.codeplex.com/wikipage?title=WatermarkTextBox&referringTitle=Home
The source is available, so you could try porting that control to Silverlight.

Resources