CPTreeController (Cappuccino) - cappuccino

what is the best way to build a binding compatible outline view datasouce in cappuccino ? i.e. a kind of CPTreeController
my source is currently a jSON object (containing objects and arrays) and I would like to display it into an outline view as well as being able to change its parameters / get notified for the changes. (Once loaded into the CPTreeController, I do not need to serialize it back to jSON, I will work directly with the datasource)
Then:
Is there a hidden CPTreeController somewhere or a similar lib ready to use ?
If I rewrite my own datasource, should I write it all from scratch or could I easily mix CPDictionaries and CPArrays to achieve this task ? (keeping in mind it should be bindings compliant)

A search through sources says there is no hidden CPTreeController so you can either write your own implementation of CPTreeController and contribute it to community or you can implement data source protocol for a specific model, something like this:
- (int)outlineView:(CPOutlineView)theOutlineView numberOfChildrenOfItem:(id)theItem
{
if (theItem == nil)
theItem = rootNode;
return [[theItem childNodes] count];
}
- (id)outlineView:(CPOutlineView)theOutlineView child:(int)theIndex ofItem:(id)theItem
{
if (theItem == nil)
theItem = rootNode;
return [[theItem childNodes] objectAtIndex:theIndex];
}
- (BOOL)outlineView:(CPOutlineView)theOutlineView isItemExpandable:(id)theItem
{
if (theItem == nil)
theItem = rootNode;
return [[theItem childNodes] count] > 0;
}
- (id)outlineView:(CPOutlineView)anOutlineView objectValueForTableColumn:(CPTableColumn)theColumn byItem:(id)theItem
{
return [[theItem representedObject] valueForKey:"name"];
}

Related

How to tell if the active document is a text document?

I'm developing a Visual Studio extension in which one of the implemented commands needs to be available only when the active document is a text document (like e.g. the Visual Studio's "Toggle Bookmark" does). The problem is that I can't figure out how to tell when that's the case.
Right now I have a half working solution. In the package's Initialize method I subscribe to DTE's WindowActivated event, and then whenever a window is activated I check if the window DocumentData property is of type TextDocument:
protected override void Initialize()
{
base.Initialize();
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
dte.Events.WindowEvents.WindowActivated += WindowEventsOnWindowActivated;
//More initialization here...
}
//This is checked from command's BeforeQueryStatus
public bool ActiveDocumentIsText { get; private set; } = false;
private void WindowEventsOnWindowActivated(Window gotFocus, Window lostFocus)
{
if (gotFocus.Kind != "Document")
return; //It's not a document (e.g. it's a tool window)
TextDocument textDoc = gotFocus.DocumentData as TextDocument;
ActiveDocumentIsText = textDoc != null;
}
The problem with this approach is that 1) Window.DocumentData is documented as ".NET Framework internal use only", and 2) this gives a false positive when a document that has both a code view and a design view (e.g. a .visxmanifest file) is open in design mode.
I have tried to use IVsTextManager.GetActiveView as well, but this is returning the last active text view opened - so if I open a .txt file and then a .png file, it returns data for the .txt file even if it's not the active document anymore.
So, how do I check if the active document is a text document, or the code view of a document that can have a designer... and if possible, not using "undocumented" classes/members?
UPDATE: I found a slightly better solution. Inside the window activated handler:
ActiveDocumentIsText = gotFocus.Document.Object("TextDocument") != null;
At least this one is properly documented, but I still have the problem of false positives with designers.
I finally got it. It's somewhat tricky, but it works and is 100% "legal". Here's the recipe:
1- Make the package class implement IVsRunningDocTableEvents. Make all the methods just return VSConstants.S_OK;
2- Add the following field and the following auxiliary method to the package class:
private IVsRunningDocumentTable runningDocumentTable;
private bool DocIsOpenInLogicalView(string path, Guid logicalView, out IVsWindowFrame windowFrame)
{
return VsShellUtilities.IsDocumentOpen(
this,
path,
VSConstants.LOGVIEWID_TextView,
out var dummyHierarchy2, out var dummyItemId2,
out windowFrame);
}
3- Add the following to the Initialize method of the package class:
runningDocumentTable = GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
runningDocumentTable.AdviseRunningDocTableEvents(this, out var dummyCookie);
4- Don't blink, here comes the magic! Implement the IVsRunningDocTableEvents.OnBeforeDocumentWindowShow method as follows:
public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
runningDocumentTable.GetDocumentInfo(docCookie,
out var dummyFlags, out var dummyReadLocks, out var dummyEditLocks,
out string path,
out var dummyHierarchy, out var dummyItemId, out var dummyData);
IVsWindowFrame windowFrameForTextView;
var docIsOpenInTextView =
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_Code, out windowFrameForTextView) ||
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_TextView, out windowFrameForTextView);
//Is the document open in the code/text view,
//AND the window for that view is the one that has been just activated?
ActiveDocumentIsText = docIsOpenInTextView && pFrame == logicalViewWindowFrame;
return VSConstants.S_OK;
}

Aurelia 2 custom elements (already sharing a view via #) doing almost the same thing, how to refactor?

Here is my problem:
Aurelia app:
a few custom elements (already sharing a view via #UseView) doing almost the same thing (specific func shoud be defined by every element itself), how to manage shared code (inkl #bindable)?
How to refactor this:
https://gist.run/?id=897298ab1dad92fadca77f64653cf32c
The "shared" code you refer to in your question is lifecycle-related stuff in your custom elements, which isn't really suited for sharing. You would need to do inheritance, and with custom elements that's setting yourself up for a lot of headaches.
Rather than sharing code, why not focus on the things which are variable and try to make them configurable? By looking at your gist, that seems by far the most straightforward solution here.
Say you have a custom element that calls a function when a property changes. This function needs to be different for some instances of the element. You could accomplish that with a bindable function, and use the .call behavior, like so:
some-element.js
import { bindable } from 'aurelia-framework';
export class SomeElement {
#bindable value;
#bindable processValue;
valueChanged(newValue, oldValue) {
if (this.processValue) {
this.processValue({ val: newValue });
}
}
}
consumer.html
<some-element value.bind="myValue" process-value.call="myFunc(val)"></some-element>
<some-element value.bind="anotherValue" process-value.call="anotherFunc(val)"></some-element>
consumer.js
myFunc(val) {
console.log("val: " + val);
}
anotherFunc(val) {
console.log("val: " + val);
}

SlickGrid CollapseAllGroups

I am trying to get dataView.collapseAllGroups() to work with SlickGrid.
The post In SlickGrid, how do I collapse grouping via javascript says to just use collapseAllGroups() but it doesn't seem to work.
Even when going to the current demo page http://mleibman.github.io/SlickGrid/examples/example5-collapsing.html and typing dataView.collapseAllGroups() into the console, it doesn't seem to do anything. Is there something else that I need to do to refresh the grid?
Edit
I was trying to get the Grid to display a tree where the groups are collapsed by default. Although I cannot get CollapseAllGroups() to work, I was able to do a hack by adding "if (item._collapsed == null) item._collapsed = true;" to myFilter function that is in the example above.
This is a rough worksound but it does the job for now until I find the real solution:
function myFilter(item) {
// Added this line:
if (item._collapsed == null) item._collapsed = true;
if (item.parent != null) {
var parent = gridData[item.parent];
while (parent) {
if (parent._collapsed) {
return false;
}
parent = gridData[parent.parent];
}
}
return true;
}
That particular example demonstrates how to implement hierarchies using custom formatters and a filter. It does NOT use the DataView's grouping feature, so the collapseAllGroups() call has no effect.

Get values from NSTextField, NSComboBox in a unified way?

I have the following method set as the action of an NSComboBox and two NSTextFields:
- (IBAction)valueChanged:(id)sender
{
if (sender == comboBox) {
[myModel setFoo1:[comboBox intValue]];
} else if (sender == intTextField) {
[myModel setFoo2:[intTextField intValue]];
} else if (sender == floatTextField) {
[myModel setFoo3:[floatTextField floatValue]];
}
}
I wondered if I could make that method into something like this, in order to increase maintainability:
- (IBAction)valueChanged:(id)sender
{
[myModel setValue:[sender value] forKey:[sender identifier]];
}
Unfortunately, it doesn't work like that. I get the following error:
[NSComboBox value]: unrecognized selector sent to instance 0x7fed42029430
How do I get the values from the controls in a uniform way (i.e. as an object), no matter if int or float? The KVC setValue:forKey: method I use on my model should be able to deduce the actual type of the value object (i.e. the kind of NSNumber in this case) just fine, right?
Or is this not possible at all? (I know I could probably use bindings to bind the UI controls to the model's value fields, but that's not what I want to do.)
Since both NSTextField and NSComboBox are subclasses of NSControl, you should be able to use -(id)objectValue to get the control's value (or selected value) in a uniform way.

Safe to hold context within a Dictionary

OK so my question is self explanatory, here is some code so you can understand a little more.
public Dictionary<string,VcardWindow> VcardWindowManager
= new Dictionary<string,VcardWindow>();'
And access like so:
public void ShowVcardWindow(string VcardOwner)
{
VcardWindow Window;
if(VcardWindowManager.ContainsKey(VcardOwner))
{
Window = VcardWindowManager[VcardOwner];
}
else
{
Window = new VcardWindow(VcardOwner);
//Startup Code
VcardWindowManager.Add(VcardOwner,Window);
}
//Invoker here
}
Is by storing windows in a dictionary OK? Are there other means that are faster and safer?
An instance of a Form is an object like any other, and so you can store its reference in a Dictionary. Using a Dictionary in this case is the correct way to store a collection of objects that need to be accessed according to a key, in a single-threaded scenario.

Resources