Designing custom NSTextView - cocoa

I need to design a custom text view that displays logs that my application produces. Logs have a specific packed binary format, each entry includes a number of fields besides an actual string (log level, date, source). Now these logs can be huge, hundreds of megabytes of data. I need to implement features such all quick filtering based on message type/source, searching, control over memory layout, etc. Since NSTextView supports most of these features i decided to start from there.
I obviously need my custom text storage to provide access to my packed log format, to load new strings on demand when user scrolls the log view window. I also need to selectively display lines of logs based on current active filters (display only warnings for example) without reloading the whole text into the view again, just filtering out the lines as they are displayed.
I have looked at NSTextStorage and it advises to overload -string, which does not exactly fits the purpose. Could anyone please give a couple of pointers to guide my further research? I am relatively new to cocoa's text handling.

Not a direct answer to your question, but a possible alternative good enough for Apple:
Why not do as Console.app does with proper system logs? Each log entry (though it might be multiple lines) starts with a very specific format. Console.app uses an outline view (an entry has a child row if the line is too long for the table row to keep all entries the same size for easy perusal). Check it out in /Applications/Utilities/Console.app under a standard log.
The benefits: simple selection of entire entry, very easy search filtering, alternating row colors make individual entries easier to see, you could use variable row height to show the whole message if you didn't like the truncated / disclosure approach.

Related

Python gui table whose cells are drop down lists with dynamic content based on the content of other drop-down-list-cells of the same gui-table

I am trying to port to Python 3.x a small gui application that I have written in Matlab.
The app contains a Matlab uitable, with which you can program bitfields of registers of a microcontroller. Actually you can create a panel which groups some register-bitfields that are important to you for debugging at a specific point in time (kind-of a watch window in a compiler IDE).
It looks like this:
Gui Table used to write to register bitfields of a microcontroller
So, each row of the table can be used to program a specific register bitfield.
There are 4 columns:
1. Register name (drop down list)
2. Bitfield name (drop down list)
3. Value to write (string)
4. Format (Hex or Dec drop down list, irrelevant here)
In order to use this application, one first clicks on the register name drop down list, where all registers are shown (detail: using a text box one can apply filters to narrow down the list size).
When the register is selected, the drop down list of the bitfield column updates automatically so that it contains only the bitfields of the chosen register. This happens with the help of a callback function.
Then, the user has to enter a value and a format, and only if all cells contain valid content, then a register write command is issued (via some debugger interface).
This worked OKish; sometimes the bitfields list was actually the one of the previous register added in the table, but this could be detected and have the entry cleared so that the user can try again. Also when the number of rows becomes very high and scroll bars appear, then if the user tries to enter a register at the bottom, every time they click on the drop down list, they can choose an entry and then the scroll bar position will automatically change showing the beginning of the table. This makes the process of entering registers quite cumbersome. As far as I know, the uitable of Matlab did not have accessible properties to control this behavior.
Since I am a hw engineer with limited sw technologies knowledge, I am wondering if there is a natural way to support this in Python 3.x, say with some structured (e.g. xml) data container that can naturally map to a gui component, without so much callback programming and data validation. The ideal behavior would be that the user starts to type directly at the register name drop down list (not possible in Matlab), and dynamically gets a filtered version of the register names list.
I am completely new to python, just installed Anaconda. I have found some interesting classes in PyQt:
QListView Class,
QListWidget Class,
QTableView Class,
QTableWidget Class.
However, I would like to have the combined functionality of the tableview with a listview, as is the case with the uitable in Matlab. Or even better, a text edit input that turns into a drop down list after typing a few letters.
The pyqtgraph.tablewidget seems to augment the functionality of QTableWidget, but I think this is still not what I need.
So, if the above is not possible, or would involve heavy programming, maybe all I need is to change approach and have a single separate search box with autocompletion, which looks into a "flattened" version of the registers database, and returns results in the form my_register_1.my_bitfield_1 (maybe allowing the user to search simultaneously at both register and bitfield names). When the user clicks on one item of the "autocompletion list", then the selected entry is mapped to the currently selected line in the tableview, adding both the register name and bitfield in read-only table cells. The "value to write" cell should still be editable, and when it gets valid data it should trigger register write command...
I would appreciate if you could guide me where to look. Thanks!
You should use the Qt model/view architecture. This allows you to have a representation of your data (the "model"), which is separate from how that data is represented (the "view"). So you set up a table of data, and then set up a view to represent that data. When you switch between different data sets, you tell the view to display the new data set. The tutorial I linked to explains this in some detail

Scrollable list of subpanels in labview

I am making a program that sweeps software parameters of a DUT and logs measurements from various instruments while doing so.
To make this program more flexible, I want the user to be able to configure an arbitrary set of instruments (including multiple of the same kind) to log measurements from. Each instrument has different configuration parameters.
What i need is a dynamic UI, where I can add (and remove) Instruments and have a different configuration UI for each instrument.
I made a little sketch of what I have in mind: UI proposal
What I tried so far is to have an Array of a Cluster with a Subpanel in it, but all the Subpanels in the Array show the same VI.
A simple way of doing this is 2 subpanels. One stays on the main screen with your current vi running. When you want to switch vis load the new vi into the off screen subpanel. Move the positions of the subpanels so that the new one is on screen. Unload the old one and allow the new one to start. The old one is now ready for the next vi to run
Instead of a cluster or an array, the basic idea for making something like this work is to have one subpanel which will contain multiple subpanels inside it and populate/position/resize/show/hide them, etc.
See this thread for a discussion and a basic example I posted there - http://forums.ni.com/t5/LabVIEW/Independent-cursors-on-array-of-cluster-of-graphs-or-work-around/m-p/2319700#M728304
(Note - that thread shows a discussion and expansion on the topic. The original simpler example is here - http://forums.ni.com/t5/LabVIEW/User-interface-problem-list-of-clusters/m-p/2311770#M726599 )
While I always liked the idea of this, I never actually needed it for an actual UI, so I don't think I have anything to add beyond this example. Also note that the example is very crude and only meant to demonstrate this concept.
Note that there are two ways of handling the number of panels - have enough to be displayed and control which VIs they show based on the scroll bar or create "enough" subpanels and control their visibility.

Is there a SetText message for the Win32 ListBox control?

This is easy in .NET (not my question) but I'm trying to figure out if it is possible to simply change the text of a string in a Win32 list box control given an index.
There is a GetText function that takes an item index but nothing to change the text of an existing item/string. My workaround will be to remove it and add it back in the box (which is also a weird prospect since there is no single command to add a string + item data -- these must be done carefully by inserting the string and then setting the item data on the index of the inserted string, which is tricky (not possible?) with sorting active).
Yes, the lack of a LB_SETITEMTEXT message is a bit weird.
You should put your Delete+Insert+SetData calls between calls to WM_SETREDRAW...
At the risk of being off topic...
I tend to use the ListView control all of the time. You'll want it in report view to mimic a listbox, and, as a plus, it supports multiple columns.
Oh.. and it has a LVM_SETITEM Message :)
http://msdn.microsoft.com/en-us/library/bb761186(v=VS.85).aspx
Although this question is old, but I think this documentation presented by Microsoft will be able to answer anyone questions based on this one.
So according to Microsoft documentation which you can find here
Changes the text of a list-view item or subitem. You can use this
macro or send the LVM_SETITEMTEXT message explicitly.
void ListView_SetItemText(
hwndLV,
i,
iSubItem_,
pszText_
);
And it also presents other macros for managing the list box. You can build a wrapper around this macros to simplify handling list view controls, etc.

Readymade Cocoa Spotlight UI Components

I'm new to developing on the Mac and am looking to implement an interface similar to Spotlight's - the main part which seems to be an expanding table/grid view.
I was wondering if there is a component Apple provides for creating something like this or is available open source else where.
Of course if not I'll just try and work something out myself but it's always worth checking!
Thanks for your help in advance.
New Answer (December, 2015)
These days I'd go with a vertical stack view ( NSStackView ).
You can use its hiding priorities to guarantee the number of results you show will fit (it'll hide those it can't). Note, it doesn't reuse views like a table view reuses cell views, so it's only appropriate for a limited number of "results" in your case, especially since it doesn't make sense to add a bunch of subviews that'll never appear. I'd go so far as to say outright you shouldn't use it for lists of things you intend to scroll (in this case, go with a table view).
The priority setting can be used to make sure your assumption of what should be "enough" results doesn't cause ugly layout issues by letting the stack view "sacrifice" the last few.
You can even emulate Spotlight's "Spotlight Preferences" entry (or a "show all" option) by adding it last and setting its priority to required (1000) so it always stays put even if result entries above it are hidden due to lack of space.
Lately all my UI designs for 10.11 (and beyond) have been making heavy use of them. I keep finding new ways to simplify my layouts with them. Given how lightweight they are, they should be your go-to solution first unless you need something more complex (Apple engineers stated in WWDC videos they're intended to be used in this way).
Old 2011 Answer
This is private Apple API. I don't know of any open-source initiatives that mimic it off-hand.
Were I trying to do it, I might use an NSTableView with no enclosing scroll view, no headers, two columns, right-justified lighter-colored text in the left column, the easily-googled image/text cell in the right column, with vertical grid lines turned on. The container view would observe the table view for frame changes and resize/reposition accordingly.
Adding: It might be a good idea also to see if the right/left justified text (or even the position of the columns) is different in languages with different sweep paths. Example: Arabic and Hebrew are read right-to-left. Better to adapt than to say "who cares" (he says flippantly while knowing full well his own apps have problems with this sort of thing :-)). You can test this by making sure such languages are installed on your computer, then switching between them and testing out Spotlight. Changing languages shouldn't pose an issue since the language switching UI doesn't rely on reading a foreign language. :-)

Saving/Associating slider values with a pop-up menu

Following on from a question I posted yesterday about GUIs, I have another problem I've been working with. This question related to calculating the bending moment on a beam under different loading conditions.
On the GUI I have developed so far, I have a number of sliders (which now work properly) and a pop-up menu which defines the load case. I would like to be able to select the load case from the pop-up menu and position the loads as appropriate, in order to define each load case in turn. The output that I need is an array defining the load case number (the rows) and a number of loading parameters (the itensity and position of the loads, which are controlled by the sliders).
The problem I am having is that I can produce this array (of the size I need) and define the loading for one load case (by selecting the pop-up menu) using the sliders, but when I change the popup menu again, the array only keeps the loading for the load case selected by the pop-up menu.
Can anyone suggest an approach I can take with (specifically to store the variables from each load case) or an example that illustrates a similar solution to the problem?
The probem may be a bit vague, so please let me know if anything needs clearing up.
Many Thanks,
James
You could use Application Data to store the current loading case and have a application data structure to store the values of each slider for the different loading cases.
In short, you could use the setappdata and getappdata to save and load the data you need. Mathworks has more information here.

Resources