Javafx - Clipview to a Group? - javafx

Can I apply clipview to a vertical expanding Group? Time to time I'm appending text to a group and want to use scrollbar to navigate in that group. The scrollbar part is working when I assign it to the group itself but want to limit the size of the group by using clipview.
Anyone having experience in this?

The clipview basically just creates a view portal into its content. Here is a simple example. (You would need to handle the clipY properly when clip.maxY is < scene.height).
var group = VBox { };
var ndx:Integer = 0;
def cv : ClipView = ClipView {
pannable: false
node: group
width: bind scene.width - sb.layoutBounds.width
height: bind scene.height
};
var scene: Scene;
var sb: ScrollBar;
Stage {
title: "ClipView Test"
scene: scene = Scene {
width: 250
height: 80
content: [
cv,
Rectangle {
layoutX: bind scene.width - sb.layoutBounds.width - 50
width: 50
height: 50
fill: Color.RED
onMouseClicked: function(e) {
insert Text { content: "Text - {ndx++}" } into group.content;
if(cv.maxClipY > scene.height) {
cv.clipY = cv.maxClipY;
}
}
}
sb = ScrollBar {
vertical: true
layoutX: bind scene.width - sb.layoutBounds.width
height: bind scene.height
min: 0
max: bind cv.maxClipY
value: bind cv.clipY with inverse
}
]
}
}

Related

Is there a way in Vis.js to keep nodes at the same size while zooming in/out?

I'm wondering whether there is or not a way to keep the size of nodes, in a Vis.js network, always at the same size while zooming in/out
I the Options
{
size: 10,
scaling: {
min: 10,
max: 10
}
}
but this setting doesn't work at all, I also tried with
customScalingFunction: function (min,max,total,value) {
return 1;
}
thinking that this function would run any time there is a re-rendering of the network.
This can be achieved by changing the nodes.size and nodes.font.size options when the network is zoomed. Details on these options can be found in the documentation here and details on the zoom event here. As per the documentation the nodes.size option is only applicable to shapes which do not have the label inside of them.
Example snippet adjusting the size on zoom:
// create an array with nodes
let nodes = new vis.DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" },
]);
// create an array with edges
let edges = new vis.DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 },
{ from: 3, to: 3 },
]);
// create a network
const container = document.getElementById("mynetwork");
const data = {
nodes: nodes,
edges: edges,
};
let options = {
nodes: {
shape: 'dot',
size: 10,
font: {
size: 10
}
}
};
const network = new vis.Network(container, data, options);
// Set the initial node size once before network is drawn
network.once("beforeDrawing", function() {
setNodeSize(network.getScale());
});
// Adjust size on zoom
network.on("zoom", function (params) {
setNodeSize(params.scale);
});
function setNodeSize(scale){
// Update node size dependent on scale
options.nodes.size = (10 / scale);
options.nodes.font.size = (10 / scale);
network.setOptions(options);
}
#mynetwork {
width: 600px;
height: 160px;
border: 1px solid lightgray;
}
<script src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
<div id="mynetwork"></div>
Regarding the scaling options, I don't believe they can be used to achieve this. Scaling is relative to other nodes on the network, not the viewport / zoom. A quick example to illustrate changing the scaling value is https://jsfiddle.net/34b682qs/. Clicking on the button toggles the scaling value set for each node in sequence between 10 and 20. When all nodes have the same value the network scales them all to be the same size regardless of if that value is 10 or 20. Therefore adjusting this value on zoom would have no effect.

Can I Replace SimpleRow with Image if no modelData avaliable

I have a ListView, where the currently displayed modelData changes as a button cycles through several department options. If one of these departments has no data, my delegate continues showing the previous list data until it reaches a new section of modelData with data.
What I want to do, is when the model is 'empty' (being undefined, which may happen when the key it's looking for is yet to be created in my Firebase Database, or no items are currently visible), text/image is shown instead; i.e, "Move along now, nothing to see here".
My model is drawn from JSON, an example is below. and my calendarUserItems is the root node of multiple children within my Firebase Database, the aim of my AppButton.groupCycle was too add a further direction to each child node, filtering the data by this to view and edit within the page.
A sample of my code is:
Page {
id: adminPage
property var departments: [1,2,3,4]
property int currGroupIndex: 0
AppButton {
id: groupCycle
text: "Viewing: " + departments[currGroupIndex]
onClicked: {
if (currGroupIndex == departments.length - 1)
currGroupIndex = 0;
else
currGroupIndex++;
}
}
ListView {
model: Object.keys(dataModel.calendarUserItems[departments[currGroupIndex]])
delegate: modelData.visible ? currentGroupList : emptyHol
Component {
id: emptyHol
AppText {
text: "nothing to see here move along now!"
}
}
Component {
id: currentGroupList
SimpleRow {
id: container
readonly property var calendarUserItem: dataModel.calendarUserItems[departments[currGroupIndex]][modelData] || {}
visible: container.calendarUserItem.status === "pending" ? true : false
// only pending items visible
// remaining code for simple row
}
}
}
}
an example of JSON within my dataModel.calendarUserItems is:
"groupName": [
{ "department1":
{ "1555111624727" : {
"creationDate" : 1555111624727,
"date" : "2019-03-15T12:00:00.000",
"name" : "Edward Lawrence",
"status": "pending"
},
//several of these entries within department1
},
},
{ "department2":
{ "1555111624727" : {
"creationDate" : 1555111624456,
"date" : "2019-05-1T12:00:00.000",
"name" : "Katie P",
"status": 1
},
//several of these entries within department2
},
}
//departments 3 & 4 as the same
]
If departments 2 and 3 have modelData, yet 1 and 4 do not, I want the text to display instead, and the ListView emptied, instead of showing the previous modelData.
I have tried playing with the image/text visibility but the issue lays more with clearing the modelData and I'm unsure where to begin?
Any help is greatly appreciated!
I have achieved the display by using the following as my delegate:
delegate: {
if (!(departments[currGroupIndex] in dataModel.calendarUserItems) ) {
return emptyHol;
}
var subgroups = Object.keys(dataModel.calendarUserItems[departments[currGroupIndex]]);
for (var i in subgroups) {
var subgroup = dataModel.calendarUserItems[departments[currGroupIndex]][subgroups[i]];
modelArr.push(subgroup);
}
var modelObect = modelArr.find( function(obj) { return obj.status === "pending"; } );
if (modelObect === undefined) {
return emptyHol;
}
return currentGroupList;
}
Then when my AppButton.groupCycle is pressed, I have added modelArr = [] to clear the array on each press, this works as intended.
Thanks!

Is there a way to use absolute and relative positions for series in QML ChartView?

I want to ensure that in the following code, the red line is always on top, does qml have any features that would allow me to do this, such as a relative or absolute positing option.
ChartView{
anchors.fill: parent
id: chart
ValueAxis{
id: axisY
min: 0
max: 1
}
ValueAxis{
id: axisX
min: 0
max: 1
}
property var redSeries;
property var blackSeries;
Component.onCompleted: {
redSeries = chart.createSeries(chart.SeriesTypeLine, "red", axisX, axisY);
redSeries.color = "red";
redSeries.append(0.3,0);
redSeries.append(0.3,1);
redSeries.width = 3;
}
Timer{
interval: 1000
running: true
triggeredOnStart : false
onTriggered: {
chart.blackSeries = chart.createSeries(chart.SeriesTypeLine, "black", axisX, axisY);
chart.blackSeries.color = "black";
chart.blackSeries.append(0,0.5);
chart.blackSeries.append(1,0.5);
chart.blackSeries.width = 3;
}
}
}
EDIT:
What's being displayed at the moment is what's in the first image, however I want the second image to be displayed while still generating the second black line after the red line
sorry for the misunderstanding. I've thought about 'top' as top of y axis, not as 'z' -). As for the issue I didn't found any solution. There is no any way to control z-order of the series. The only stupid workaround I see is to delete the red line and to add it after all time you add the black one.
May be like this:
ChartView {
...
Timer {
...
onTriggered: {
chart.blackSeries = chart.createSeries(chart.SeriesTypeLine, "black", axisX, axisY);
...
chart.removeSeries(chart.redSeries);
}
}
onSeriesRemoved: {
var newSeries = chart.createSeries(chart.SeriesTypeLine, "red", axisX, axisY);
newSeries.color = "red";
for(var i = 0;i <series.count;i ++)
{
var p = series.at(i);
newSeries.append(p.x, p.y);
}
chart.redSeries = newSeries;
}

How to programmatically set navigator handles in highstock?

Is there a way I can programmatically set the markers in highstock navigator, even though I want to keep marker to be set to { type: "day", count: 1, text: "1d" } but not display Zoom 1d.
It's possible to set extremes without rangeSelector using xAxis.setExtremes() method: http://plnkr.co/edit/bRnV1lyJHmmx7YURTggq?p=preview
chart: {
renderTo: 'container',
height: 600,
events: {
load: function() {
var max = this.xAxis[0].max,
range = 24 * 3600 * 1000; // one day
this.xAxis[0].setExtremes(max - range, max);
}
}
},

Sencha Touch won't hide my List

I have a Map and a List inside the same container with 2:5 flex ratio set. I would like to be able to toggle doubleclick on the map to maximize it to fill the container or reset it back to the original size depending whether the List is hidden. I wrote the function below and bound it to the map's dblclick event. I see it go into this function but it has no effect on what I see. Any ideas why my list won't animate and hide?
google.maps.event.addListener(that.getMap(), 'dblclick', function () {
var list = Ext.ComponentQuery.query('#BuildingList')[0];
var height = list.getHeight();
if (list.isHidden()) {
list.show(Ext.Anim({
easing: 'easeInOut',
duration: 1000,
autoClear: false,
from: {
opacity: 0,
height: '0px'
},
to: {
opacity: 1,
height: list.getHeight() + 'px'
}
}));
} else {
list.hide(Ext.Anim({
easing: 'easeInOut',
duration: 1000,
autoClear: false,
from: {
opacity: 1,
height: list.getHeight() + 'px'
},
to: {
opacity: 0,
height: '0px'
}
}))
}
});
The best way to do this sort of thing I found was to set the flex to 0 of the list on the dblclick event (which I had to add as an override to the map), as follows:
that.addAfterListener('dblclick', function (view, map, zoomlevel, eOpts) {
var list = view.getParent().down('buildings');
Ext.Anim.run(list, 'fade', {
easing: 'easeInOut',
autoClear: false,
duration: 300,
after: function () {
list.setFlex(0);
}
});
});

Resources