JGraphX - Autolayout edges only - jgraphx

Is there anyway i can a run auto-layout on graph edges only?
I have a lot of fixed vertexes that i do not want to move/rearrange, but i do want to fix edges that overlap my cell/vertexes.
Is there any way to do this?

The layouts, namely mxIGraphLayout implementations, concern themselves with visible cells only, and they access those via the mxGraph object API. So the proper solution is to subclass mxGraph and override the isCellVisible(Object cell) method according to your needs. This way you'd create an alternate view of your graph.
Of course, you can also change the actual cell visibility in the model (graph.getModel().setVisible(cell, false)) and restore it back after the layout execution. But that seems like a hack.
Alternatively you could subclass the layout class itself and override these methods:
public boolean isVertexMovable(Object vertex)
{
return graph.isCellMovable(vertex);
}
public boolean isVertexIgnored(Object vertex)
{
return !graph.getModel().isVertex(vertex)
|| !graph.isCellVisible(vertex);
}
public boolean isEdgeIgnored(Object edge)
{
mxIGraphModel model = graph.getModel();
return !model.isEdge(edge) || !graph.isCellVisible(edge)
|| model.getTerminal(edge, true) == null
|| model.getTerminal(edge, false) == null;
}

Related

onApplyWindowInsets(WindowInsets insets) not getting called

I am currently using a custom view that extends a Constraint layout but I it does not trigger this overridden method in the view onApplyWindowInsets(WindowInsets insets) not sure what went missing.
class TestCustomView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
init {
}
//This method one not get called
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
return super.onApplyWindowInsets(insets)
val statusBarHeight = insets.systemWindowInsetTop
}
override fun fitSystemWindows(insets: Rect): Boolean {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
// Intentionally do not modify the bottom inset. For some reason,
// if the bottom inset is modified, window resizing stops working.
insets.left = 0
insets.top = 0
insets.right = 0
}
return super.fitSystemWindows(insets)
}
}
Once the insets are consumed, propagation down the hierarchy stops. It looks like something higher up is consuming what's available. See isConsumed() of WindowsInset.
Check if these insets have been fully consumed.
Insets are considered "consumed" if the applicable consume* methods have been called such that all insets have been set to zero. This affects propagation of insets through the view hierarchy; insets that have not been fully consumed will continue to propagate down to child views.
I found that without the android:windowTranslucentStatus property set to true, onApplyWindowInsets is never called. I discovered this on reading this unanswered question.
In styles.xml:
<style name="ExampleTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
I would love to understand why this is so, and if there is a way to have it called without requiring this attribute change.
I think if you wanna reset it's windowInsets callback state, you should change sysUiVisibility params to let fitsSystemWindows work normally. Because fitsSystemWindows is a key to consume the windowInsets. You can learn more from android source code, of course, you need time.

Disable copy/paste on Xamarin forms input field i.e. Entry

I am working on disabling copy/paste option menus on xamarin forms Entry, I am able to disable copy option using IsPassword=true attribute but this attribute also converts the normal input field to password field, which is not a requirement.
<Entry IsPassword="true" Placeholder="Password" TextColor="Green" BackgroundColor="#2c3e50" />
Thanks in advance.
This has to do with how Forms functions. Using iOS as the example here, the CanPerform override referred to in the other answer's Bugzilla issue is using the UIMenuController as the withSender and not the UITextField itself that might otherwise be expected. This is because the EntryRenderer class is a ViewRenderer<TView, TNativeView> type and subsequently is using whatever TNativeView (in this case, the UITextView) has in its CanPerform. Because nothing is going to be overridden by default, one still sees all of the cut/copy/paste options in the UIMenuController.
As a result, there would be a couple options. You could first make the modification where if you don't want copy/paste but are fine with getting rid of everything else, you can use UIMenuController.SharedMenuController.SetMenuVisible(false, false) in a custom renderer inheriting from EntryRenderer. If you look around on SO, there are similar questions where this is a possible route.
Alternatively, you can create a "true" custom renderer inheriting from ViewRenderer<TView, TNativeView> as ViewRenderer<Entry, YourNoCopyPasteUITextFieldClassName>. The class inheriting from UITextField can then override CanPerform as something like follows:
public override bool CanPerform(Selector action, NSObject withSender)
{
if(action.Name == "paste:" || action.Name == "copy:" || action.Name == "cut:")
return false;
return base.CanPerform(action, withSender);
}
This will require more effort because the custom renderer will not have the same behavior as the EntryRenderer, but as Xamarin.Forms is now open source, you could look to it for some ideas as to how the EntryRenderer functions normally. Something similar would likely have to be done for Android.
Edit: For Android, you can probably use this SO answer as a starting point: How to disable copy/paste from/to EditText
Another custom renderer, this time inheriting from ViewRenderer<Entry, EditText>, and create a class inside of it like this (in the most basic form):
class Callback : Java.Lang.Object, ActionMode.ICallback
{
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
{
return false;
}
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
{
return false;
}
public void OnDestroyActionMode(ActionMode mode)
{
}
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
{
return false;
}
}
Then, in your OnElementChanged method, you can set the native control and the CustomSelectionActionModeCallback value:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.CustomSelectionActionModeCallback = new Callback();
}
}
Doing something like the following appears to disable all of the copy/paste/cut functionality on the custom entry as far as the toolbar goes. However, you can still long click to show the paste button, to which I've poked around a bit hadn't found an answer yet beyond setting LongClickable to false. If I do find anything else in that regard, I'd make sure to update this.

MultiScaleImageSource GetTileLayers Explanation

I have been doing reading on MultiScaleImage source, and finding anything useful has proven to be quite difficult, thus I turn to the experts here. The specific knowledge I would like to have pertains to the GetTileLayers method. I know this method is used to get the image tiles. But I have no idea where this method is called from, or where the parameters come from or how I would use it if I subclassed the MultiScaleTileSource Class. Any insight into this method or the MSI model would be amazing but I have 3 main questions:
1. Where should/is the method GetTileLayers called from?
2. How should I change this method if I wanted to draw png's from a non-local URI?
3. Where can I find some reading to help with this?
In order to create a custom tile source, you would subclass MultiScaleTileSource and override the GetTileLayers method, as shown in the example below, which defines an image consisting of 1000*1000 tiles of size 256x256 pixels each.
public class MyTileSource : MultiScaleTileSource
{
public MyTileSource()
: base(1000 * 256, 1000 * 256, 256, 256, 0)
{
}
protected override void GetTileLayers(
int tileLevel, int tilePositionX, int tilePositionY,
IList<object> tileImageLayerSources)
{
// create an appropriate URI for tileLevel, tilePositionX and tilePositionY
// and add it to the tileImageLayerSources collection
var uri = new Uri(...);
tileImageLayerSources.Add(uri);
}
}
Now you would assign an instance of your MyTileSource class to your MultiScaleImage control:
MultiScaleImage msImage = ...
msImage.Source = new MyTileSource();

Use ScaleGestureDetector with GestureDetector?

In my Android app I have an ImageView where I'd like the user to be able to fling it left/right/up/down to change the image (static maps) to the adjacent one. But in addition, I'd like pinch-zoom abilities and a map itself.
I can get either flinging OR pinch-zooming to work, but not together. I'm using GestureDetector (with a SimpleOnGestureListener) for the flinging. And I'm using ScaleGestureDetector (from Making Sense of Multitouch) for the scaling.
The difficulty is to determine which gesture listener to invoke upon a touch action. This is less a coding issue, but logic issue. Upon a single finger touch action, is it a fling or scale? Even when a pinch-zoom is used, the initial MotionEvent is ACTION_DOWN. I've been trying to use the image size (intrinsic or scaled?) as a decision point. But the initial scaling operation (when image size is intrinsic and I want to zoom on it) with ACTION_DOWN seems to escape me.
Has anyone tackled this successfully previously?
You can pass the events on to both gesture detectors.
Check http://developer.android.com/training/gestures/scale.html under "More complex scaling example":
public boolean onTouchEvent(MotionEvent event) {
boolean retVal = mScaleGestureDetector.onTouchEvent(event);
retVal = mGestureDetector.onTouchEvent(event) || retVal;
return retVal || super.onTouchEvent(event);
}
Of course given the bug Ratatat is referencing, super.onTouchEvent will never be called in the above example, which may or may not be fine, depending on your use case.
The idea of Ratatat's answer is OK but we should still pass events to the gestureDetector even if we don't want to scroll, or it will be messed up.
I ended up with something like this:
scaleDetector = new ScaleGestureDetector( ... );
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (scaleDetector.isInProgress()) {
// don't allow scrolling while scaling
return false;
}
// handle scrolling
return true;
}
}
And then onTouchEvent's implementation should be like in aij's answer:
boolean result = scaleDetector.onTouchEvent(event);
result = gestureDetector.onTouchEvent(event) || result;
return result || super.onTouchEvent(event);
Finally found the answer on a link:
http://code.google.com/p/android/issues/detail?id=42591
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = mScaleGestureDetector.onTouchEvent(event);
// result is always true here, so I need another way to check for a detected scaling gesture
boolean isScaling = result = mScaleGestureDetector.isInProgress();
if (!isScaling) {
// if no scaling is performed check for other gestures (fling, long tab, etc.)
result = mCommonGestureDetector.onTouchEvent(event);
}
// some irrelevant checks...
return result ? result : super.onTouchEvent(event);
}

Controller selection

In my title screen, i have a code saying that the first controller using A is the PlayerIndex.one.
Here is the code:
public override void HandleInput(InputState input)
{
for (int anyPlayer = 0; anyPlayer <4; anyPlayer++)
{
if (GamePad.GetState((PlayerIndex)anyPlayer).Buttons.A == ButtonState.Pressed)
{
FirstPlayer = (PlayerIndex)anyPlayer;
this.ExitScreen();
AddScreen(new Background());
}
}
}
My question is: How can i use the "FirstPlayer" in other classes? (without this, there is no interest in this code)
I tried the Get Set thing but i can't make it work. Does i need to put my code in another class? Do you use other code to make this?
Thanks.
You can make a static variable say : SelectedPlayer,
and assign first player to it!
then you can call the first player through this class,
for example
class GameManager
{
public static PlayerIndex SelectedPlayer{get;set;}
..
..
..
}
and right after the loop in your code, you can say:
GameManager.SelectedPlayer = FirstPlayer;
I hope this helps, if your code cold be clearer that would be easier to help :)
Ok, so to do this properly you're going to have to redesign a little.
First off, you should be checking for a new gamepad input (i.e. you should be exiting the screen only when 'A' has been newly pressed). To do this you should be storing previous and current gamepad states:
private GamePadState currentGamePadState;
private GamePadState lastGamePadState;
// in your constructor
currentGamePadState = new GamePadState();
lastGamePadState = new GamePadState();
// in your update
lastGamePadState = currentGamePadState;
currentGamePadState = GamePad.GetState(PlayerIndex.One);
Really what you need to do is modify your class that deals with input. The basic functionality from your HandleInput function should be moved into your input class. Input should have a collection of functions that test for new/current input. For example, for the case you posted:
public Bool IsNewButtonPress(Buttons buton)
{
return (currentGamePadState.IsButtonDown(button) && lastGamePadState.IsButtonUp(button));
}
Then you can write:
public override void HandleInput(InputState input)
{
if (input.IsNewButtonPress(Buttons.A)
{
this.ExitScreen();
AddScreen(new Background());
}
}
Note: this will only work for one controller. To extend the implementation, you'll need to do something like this:
private GamePadState[] currentGamePadStates;
private GamePadState[] lastGamePadStates;
// in your constructor
currentGamePadStates = new GamePadState[4];
currentGamePadStates[0] = new GamePadState(PlayerIndex.One);
currentGamePadStates[1] = new GamePadController(PlayerIndex.Two);
// etc.
lastGamePadStates[0] = new GamePadState(PlayerIndex.One);
// etc.
// in your update
foreach (GamePadState s in currentGamePadStates)
{
// update all of this as before...
}
// etc.
Now, you want to test every controller for input, so you'll need to generalise by writing a function that returns a Bool after checking each GamePadState in the arrays for a button press.
Check out the MSDN Game State Management Sample for a well developed implementation. I can't remember if it supports multiple controllers, but the structure is clear and can easily be adapted if not.