Cannot drag and drop on full row of NSOutlineView - macos

I have an NSOutlineView in which Ive implemented Drag and Drop, its values are populate via bindings.
Everything is working for the logic that I want, which is basically the ability to drop only in-between root level items, and children are not allowed to be dragged or dropped anywhere. So Im just trying to implement a re-order if you will.
My issue comes into play with where on the view my NSOutlineView is accepting drops. It appears that its only allowing me to drop on the far left side of the row. I can't seem to drop anywhere else. My rows are View based, and have an image view.
This shows it working
This is it not working.
Heres my code for the acceptDrop.
- (NSDragOperation)outlineView:(NSOutlineView *)ov validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)childIndex {
// Check to see what we are proposed to be dropping on
NSTreeNode *targetNode = item;
// A target of "nil" means we are on the main root tree
if (targetNode == nil) {
//If were dropping on the physical item lets say no
if (childIndex == NSOutlineViewDropOnItemIndex) {
return NSDragOperationNone;
}
//otherwise we are in-between so lets return move.
return NSDragOperationMove;
} else {
return NSDragOperationNone;
}
}
Is it possible this has something to do with my view setup instead of my NSOutlineView code?
UPDATE:
It works on the very top row no matter where my cursor is, but only on the far left for all other rows.

This fixed it.
NSUInteger maxNumberOfRows = [[_hostController arrangedObjects] count];
// Check to see what we are proposed to be dropping on
NSTreeNode *targetNode = item;
// A target of "nil" means we are on the main root tree
if (targetNode == nil) {
//If were dropping on the physical item lets say no
if (childIndex == NSOutlineViewDropOnItemIndex) {
[ov setDropItem:nil dropChildIndex:maxNumberOfRows];
return NSDragOperationMove;
}
[ov setDropItem:nil dropChildIndex:childIndex];
return NSDragOperationMove;
} else {
//If its not a host we dont want to allow drop
if (![self isHost:[item representedObject]]) {
return NSDragOperationNone;
}
if (childIndex == NSOutlineViewDropOnItemIndex) {
[ov setDropItem:nil dropChildIndex: [ov rowForItem:item]];
return NSDragOperationMove;
}
return NSDragOperationNone;
}

Related

Adding a condition to Amibroker code

This is my Amibroker code for a 2 bar swing chart, I need to add a condition that if price falls below the previous swing low in one bar, then to treat it as a two bar move. The problem I have is, holding the last swing low price variable to check against todays low. I have commented the problem lines in caps. What I have I thought would work but the condition is not showing up on the swing chart. Can someone tell me what I am doing wrong.Thanks.
_SECTION_BEGIN("2 day swing");
upBar = H>Ref(H,-1);
dnBar = L<Ref(L,-1);
HighBarPrice=LowBarPrice=Null;
inLong=inShort=upCount=dnCount=fupbar=fdnbar=0;
for( i=1; i<BarCount; i++ )
{
if(inLong==0 AND inShort==0)
{
if(upBar[i])
{
upCount=upCount+1;
if(upCount==2)
{
fupbar[i] = 1;
inLong=1;
dnCount=0;
}
}
if(dnBar[i])
{
dnCount=dnCount+1;
if(dnCount==2)
{
fdnbar[i] = 1;
inShort=1;
upCount=0;
}
}
if(inLong==1)
{
if(dnBar[i])
{
dnCount=dnCount+1;
if(L[i]<LowBarPrice) {dnCount=2;} //THIS IS THE PROBLEM
if(dnCount==2)
{
fdnbar[i]=1;
inShort=1;
if(upBar[i])
{
upCount=1;
}
else
{
upCount=0;
}
continue;
}
}
if(upBar[i]) {HighBarPrice=H[i];}
if(upBar[i] AND NOT dnBar[i]){ dnCount=0;}
}
if(inShort==1)
{
if(upBar[i])
{
upCount=upCount+1;
if(H[i]>HighBarPrice) {upCount=2;}
if(upCount==2)
{
fupbar[i]=1;
inLong=1;
if(dnBar[i])
{
dnCount=1;
}
else
{
dnCount=0;
}
continue;
}
}
if(dnBar[i]) {LowBarPrice=L[i];}// DOWN BAR IN SHORT SWING SHOULD GIVE NEW LOW
if(dnBar[i] AND NOT upBar[i]){ upCount=0;}
}
}
// Swing chart drawn here
_SECTION_END();
Your LowBarPrice doesn't have an array indexer on it. Also, you initialize it as null and it stays that way because you never assign any value to it after initialization. So technically, in your condition, you're saying, if L[i] < null.
Write your conditions outside the loop. That'll create an array that will hold your price until you reference it in the loop.
So, for example, initialize LowBarPrice like this:
LowBarPrice = ValueWhen(DownBar, Ref(L,-1));
Thereafter, you'll get the price when you reference it in the loop.
if(L[i] < LowBarPrice[i])
This article really helped me get my head around looping in AmiBroker. It might give some context around your issue. The part that relates specifically to your question is under the section "Array Indexing
http://www.amibrokerforum.com/index.php?topic=50.0

How to drag and drop rows in NSTableView in Mac

I have struck with one point i.e now I have got a list of data using NSTableView but what my requirement is, able to drag and drop that rows from one row position to another row position. please give any suggestion for get out this problem. Thanks in advance.
My sample code
Within your NSTableViewDataSource subclass implement WriteRows, ValidateDrop and AcceptDrop and register which Drag/Drop targets your NSTableView accepts. In this case you are only accepting Drops from within your own NSTableView.
Assign a name that will be used for valid drag operations on this NSTableView:
// Any name can be registered, I find using the class name
// of the items in the datasource is cleaner than a const string
string DragDropType = typeof(Product).FullName;
Register the drag types for your NSTableView:
ProductTable.RegisterForDraggedTypes(new string[] { DragDropType });
Implement drag/drop methods on your NSTableViewDataSource:
public override bool WriteRows(NSTableView tableView, NSIndexSet rowIndexes, NSPasteboard pboard)
{
var data = NSKeyedArchiver.ArchivedDataWithRootObject(rowIndexes);
pboard.DeclareTypes(new string[] { DragDropType }, this);
pboard.SetDataForType(data, DragDropType);
return true;
}
public override NSDragOperation ValidateDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
tableView.SetDropRowDropOperation(row, dropOperation);
return NSDragOperation.Move;
}
public override bool AcceptDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
var rowData = info.DraggingPasteboard.GetDataForType(DragDropType);
if (rowData == null)
return false;
var dataArray = NSKeyedUnarchiver.UnarchiveObject(rowData) as NSIndexSet;
Console.WriteLine($"{dataArray}");
// Move hack for this example... you need to handle the complete NSIndexSet
tableView.BeginUpdates();
var tmpProduct = Products[(int)dataArray.FirstIndex];
Products.RemoveAt((int)dataArray.FirstIndex);
if (Products.Count == row - 1)
Products.Insert((int)row - 1 , tmpProduct);
else
Products.Insert((int)row, tmpProduct);
tableView.ReloadData();
tableView.EndUpdates();
return true;
}

If Rectangle doesn't Contains Mouse Position

I have a Rectangle which I can touch with this command below.
if ((mouse.LeftButton == ButtonState.Pressed )&&
TextureRectangle.Contains((int)MousePos.X,(int)MousePos.Y))
{
// Action;
}
But is there a Command like "Not Contains", so I wanna do something else if the user touch out of the "TextureRectangle" area?
When I click to the Rectangle that both actions starts. I really dont know where the problem is.
if (mouse.LeftButton == ButtonState.Pressed){
if(TextureRectangle.Contains((int)MousePos.X, (int)MousePos.Y)) {
music1.Play();
}
else{
music2.Play();
}
}
my problem is that music1 and music2 plays at same time if i click on the Rectangle, i want that when i click on the Rectangle that music1 plays only (here is the problem , both starts to play)and when i click out of the Rectangle should start only music2 to play ( this case is ok)
I would strongly recommend you to get a programming book / ebook and start reading it. This is basic computer logic stuff.
if (mouse.LeftButton == ButtonState.Pressed)
{
if (TextureRectangle.Contains((int)MousePos.X, (int)MousePos.Y))
{
// inside
}
else
{
// outside
}
}
OR
if (mouse.LeftButton == ButtonState.Pressed)
{
if (!TextureRectangle.Contains((int)MousePos.X, (int)MousePos.Y))
{
// outside
}
else
{
// inside
}
}

Loop through all buttons on screen for a given tag, WP7, using C#

I'm looking for a simple way to loop through all buttons onscreen for a given tag. Eg "foo". I'm using WP7, using C#. I'm very new to the platform so go easy on me :P
Googling this sort of thing isn't really working out for me either - I think I have my terminology wrong, so any tips on that too would be appreciated.
You should probably loop through all the controls on your page, check whether each one is a button, and if so check its Tag property.
Something like this...
foreach (UIElement ctrl in ContentPanel.Children)
{
if (ctrl.GetType() == typeof(Button))
{
Button potentialButton = ((Button)ctrl);
if (potentialButton.Tag = Tag)
return (Button)ctrl;
}
}
Bear in mind, though, that if you have nested controls on the page, you will need to think about recursing into any item with children to make sure you catch all the controls.
First, create a method to enumerate recursively the controls in your page:
public static IEnumerable<FrameworkElement> FindVisualChildren(FrameworkElement control)
{
if (control == null)
{
yield break;
}
for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(control); i++)
{
var child = System.Windows.Media.VisualTreeHelper.GetChild(control, i) as FrameworkElement;
if (child != null)
{
yield return child;
foreach (var grandChild in FindVisualChildren(child))
{
yield return grandChild;
}
}
}
}
Then call it and keep only the controls you want:
var buttons = FindVisualChildren(this.ContentPanel)
.OfType<Button>()
.Where(b => b.Tag is string && (string)b.Tag == "foo");
(where ContentPanel is the root element of your page)

How to hide a divider of nssplitview?

Now I want to hide or show with my condition a divider when my app run. used this delegate method:
- (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex
{
if (A)
return YES;
else
return NO;
}
but it didn't work , why? How to used this method? Thank you very much!
Further to #carmin’s note, above, overriding the NSSplitView dividerThickness property is the only thing that worked for me (specifically, returning NSRectZero from the splitView:effectiveRect:forDrawnRect:ofDividerAtIndex: NSSplitView delegate method — as detailed here – didn’t work and resulted in floating dividers disjointed from the views themselves).
Here’s the code in Swift:
override var dividerThickness:CGFloat
{
get { return 0.0 }
}
The split view sends that message to its delegate, to ask the delegate whether it should hide that divider. So, be the delegate, and answer the split view's question.
Be sure to check out the documentation. It's possible that that message won't accomplish what you want it to. The documentation lists everything you can do by responding to that message.
You can overload NSSplitView-dividerThickness and return 0 to hide all of the dividers. You can overload NSSplitView-drawDividerInRect: to have individual control over the dividers (choosing to allow super to draw the divider or not). These choices work even when the subviews are visible.
Here's how to do it in Obj-C that doesn't involve subclassing. Make sure that you've got the SplitView delegate in IB connected.
Then in your delegate class:
-(NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex
{
if ( [_splitView subviews][1].isHidden ==YES || [[_splitView subviews][1] frame].size.height < 50) //closed or almost closed
{
return NSZeroRect;
}
return proposedEffectiveRect;
}
- (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex
{
if ( [_splitView subviews][1].isHidden ==YES || [[_splitView subviews][1] frame].size.height < 50)
{
return YES;
}
return NO;
}
This will hide the divider when the split view is closed, but show it when it is open.
If you don't want them to be able to drag it even when its open, just cut out all the code in the first method and return only NSZeroRect. Do the same in the second method and only return YES.
For the sake of posterity, working with Swift you can call the delegate function splitView(_:effectiveRect:forDrawnRect:ofDividerAtIndex:) and just have it return an empty NSRect
override func splitView(_ splitView: NSSplitView, effectiveRect proposedEffectiveRect: NSRect, forDrawnRect drawnRect: NSRect, ofDividerAt dividerIndex: Int) -> NSRect {
if dividerIndex == 1 {
return NSRect()
}
return super.splitView(splitView, effectiveRect: proposedEffectiveRect, forDrawnRect: drawnRect, ofDividerAt: dividerIndex)
}
Use this class in Custom class of NSSplitView:
class customSplitView: NSSplitView {
override var dividerThickness: CGFloat {
return 0
}
}
For me it worked!

Resources