Adding mousewheel to Sencha Desktop App - extjs

So the supposed advantage to using Sencha is being able to have 1 code base for multiple platforms. I have a project I need to be on iOS, Android, PC, and Mac. I have found that I can use Sencha Touch to build to mobile devices and those handle finger swipe events automatically. The problem I have encountered is when I am building a desktop app then it doesn't respond to my mousewheel.
I have been on the Sencha forums and this question is unanswered in one place, and in another they promised support for this over 2 years ago. Any 3rd part solutions I have found either are not documented properly or won't work. Elsewhere I have been told that Sencha Touch is for mobile development but Extjs is for desktop, but I really don't want to have to build another codebase just for mousewheel.

There is a JSfiddle here where delta returns 1 when you mousewheel up, and -1 when you mousewheel down.
var doScroll = function (e) {
// cross-browser wheel delta
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
// Do something with `delta`
console.log(delta);
e.preventDefault();
};
if (window.addEventListener) {
window.addEventListener("mousewheel", doScroll, false);
window.addEventListener("DOMMouseScroll", doScroll, false);
} else {
window.attachEvent("onmousewheel", doScroll);
}
Put this code into the initialization block for your app. Now this code will get run anywhere in your app no matter which element has focus. I was lucky enough in my app that each of my pages only had 1 element that needed to be scrolled.
replaced console.log(delta); with code that determines which element is active/which element was in need of scrolling, and the code to scroll it.
var scrollMe = Ext.getCmp("componentToScroll");
var currentY = scrollMe.getScrollable().getScroller().position.y;
var pageHeight = document.getElementById("orderList").clientHeight;;
var containerHeight = 722; //the defined height of the scrollMeContainer
var newY = currentY;
if (delta === 1) {
if (currentY >= 30) {
newY = currentY - 30;
}
else {
newY = 0;
}
}
else if (delta === -1) {
if (currentY <= containerHeight - pageHeight - 30) {
newY = currentY + 30;
}
else {
newY = containerHeight - pageHeight;
}
}
scrollMe.getScrollable().getScroller().scrollTo(0, newY);

Related

how to decide rotation of a marker or pointer on a 3d .obj Object so that marker will look like it is pointing to some area of 3D object

I am looking something like this ( https://jsfiddle.net/xg1o4ekr/378/ ) instead of globe imagine various other shapes of 3D object and marker coming outwards. Since my 3d object is not circle i cannot use the given above code
On clicking a loaded .obj 3D model, there will a pointer rendered on a clicked position(raycaster is used). using three js geometry shapes i have created a pointer. that pointer will render on a clicked position. how to determine pointer’s rotation. (it should dynamically decide the rotation of the pointer)
onMouseClick = (event) => {
event.preventDefault();
// calculate objects intersecting the picking ray
var intersects = this.getIntersects(event.layerX, event.layerY);
if (intersects.length > 0) {
var res = intersects.filter(function (res) {
return res && res.object;
})[0];
if (res && res.object) {
this.selectedObject = res.object;
console.log(res);
const Pointer = this.createPointer();
var g2 = new THREE.Group();
g2.add(Pointer.cone);
g2.add(Pointer.sphere);
g2.position.set(res.point.x, res.point.y, res.point.z);
//g2.rotation.set(res.point.x, res.point.y, res.point.z); //not working fine
g2.rotateX(0.7);
g2.rotateZ(0.9);
g2.rotateY(1);// not working fine
this.scene.add(g2);
}
}
}
getIntersects = (x, y) => {
x = (x / this.width) * 2 - 1;
y = - (y / this.height) * 2 + 1;
this.mouseVector.set(x, y);
this.raycaster.setFromCamera(this.mouseVector, this.camera);
return this.raycaster.intersectObject(this.group, true);
}
Interesting question. It's late here so i wont be able to try code, but maybe this helps?
Does the object you are clicking on have normals?
You can find it in intersets[0].face.normal (or .vertexNormals).
You can align the pointer with that..
var normal = intersects[0].face.normal:
var axis = new THREE.Vector3(0, 1, 0); //(or maybe -1? i'm not sure, play around)
g2.quaternion.setFromUnitVectors(axis, normal);
and if you want to set the pointer at a distance from the surface;
var distance = 4;
g2.position.add( normal.multiplyScalar(distance) );
Also, instead of creating a pointer everytime, why not creating it once and do pointer.clone()?

Glitchy Dragging an object

I have been working on a simple drag feature for my project. I have a touch form which handles all event inputs. My drag implementation works fine, until I move my mouse rapidly. I have heard of getDragRegionStatus() which gets the sensitivity of the event (i could be reading the API wrong). Would this be an option for me? Example
#Override
public void pointerDragged(int[] x, int[] y) {
if(RectController.top.contains(x[0], y[0])) {
PersonalizedData.touchTopX = x[0];
PersonalizedData.touchTopY = y[0];
}
else if(RectController.bottom.contains(x[0], y[0])) {
PersonalizedData.touchTopX = x[0];
PersonalizedData.touchTopY = y[0];
}
if(x.length >= 2 && y.length >= 2 && RectController.top.contains(x[1], y[1])) {
PersonalizedData.touchTopX = x[1];
PersonalizedData.touchTopY = y[1];
}
else if(x.length >= 2 && y.length >= 2 && RectController.bottom.contains(x[1], y[1])) {
PersonalizedData.touchTopX = x[1];
PersonalizedData.touchTopY = y[1];
}
}
I am overriding the pointerDragged with array parameters for multiple touch support. In the end, I will have a top and bottom box, which can be dragged concurrently.
Is there a better way to handle drag events than this? Thanks in advance!
A better approach would be to "select" the currently dragged component in pointerPressed(). Then in pointerDragged, you don't do this check. You just assume that the item that was selected in pointerPressed is the thing you're dragging.
In pointerReleased, you "unselect" the dragged component.

Mouse Over event for corners of screen wpf windows

As the title suggests, I want to get a mouse over event at the corners of desktop. I tried to do it by getting the position of the mouse and polling it continuously to check if it is one of the edge coordinated and then trigger the event but I think thats bad way to do it. I tried to use the library MouseKeyHook but it wasn't useful for me to generate the necessary event.
Is there any better way to get mouse over events to the corners of the screen ?
I tried to improve the code by adding the following, but for some reason the mouse over to the corners isn't triggering the action.
public async void callMainLoop() {
var slowTask = Task<Boolean>.Factory.StartNew(() => mainMethodLoop(GetMousePosition()));
await slowTask;
}
public bool mainMethodLoop(Point point) {
while (true) {
double xRes = System.Windows.SystemParameters.PrimaryScreenWidth - 1;
double yRes = System.Windows.SystemParameters.PrimaryScreenHeight - 1;
if (point.X == 0 && point.Y == 0) {
if (comboBox0.SelectedItem != null) {
executeAction(comboBox0.SelectedItem.ToString());
return true;
}
}
return false;
}
}
I am not calling this in the constructor, there ins't any freezing now.

Crosszoom in a sencha chart with inner padding

I have a sencha chart with crosszooming and innerPadding like the one in the fiddle. The problem I'm experiencing is that it is not possible to pull the rectangle of the cross zoom completly down to the x-axis and to the right side of the chart. When I remove the innerPadding of the chart everything works fine.
https://fiddle.sencha.com/#fiddle/mh8
Is there a workaround for this problem?
I've forked your fiddle with a fix, here: https://fiddle.sencha.com/#fiddle/mih
NOTE: You question is tagged with Touch2.1 but your fiddle is in 2.4.1
When you define your innerPadding, the innerRegion for the chart is calculated based on your padding.
Excerpt from the source of CartesianChart
shrinkBox.left += innerPadding.left;
shrinkBox.top += innerPadding.top;
shrinkBox.right += innerPadding.right;
shrinkBox.bottom += innerPadding.bottom;
innerWidth = width - innerPadding.left - innerPadding.right;
innerHeight = height - innerPadding.top - innerPadding.bottom;
me.setInnerRegion([shrinkBox.left, shrinkBox.top, innerWidth, innerHeight]);
Now inside the onGesture (protected function) handler of CrossZoom, it actually checks the innerRegion of your chart and if your current x or y is greater than the width or height (you get this from the innerRegion of the chart) of the chart respectively, it's reset to the width/height of the chart (width and height is ). Thus, you are limited inside the padded area.
Is there a workaround for this problem?
You can work around this by overriding this behavior, but it's the expected behavior as far as Sencha is concerned.
Override onGesture function of CrossZoom so that it takes the padding offset into consideration.
//onGesture implementation in CrossZoom
onGesture: function (e) {
var me = this;
if (me.zoomAnimationInProgress) {
return;
}
if (me.getLocks()[me.getGesture()] === me) {
var chart = me.getChart(),
surface = me.getSurface(),
region = chart.getInnerRegion(),
chartWidth = region[2],
chartHeight = region[3],
xy = chart.element.getXY(),
x = e.pageX - xy[0] - region[0],
y = e.pageY - xy[1] - region[1];
if (x < 0) {
x = 0;
} else if (x > chartWidth) {
x = chartWidth; // this is where it limits you in the x-axis
}
if (y < 0) {
y = 0;
} else if (y > chartHeight) {
y = chartHeight; // this is where it limits you in the y-axis
}
me.selectionRect.setAttributes({
width: x - me.startX,
height: y - me.startY
});
if (Math.abs(me.startX - x) < 11 || Math.abs(me.startY - y) < 11) {
me.selectionRect.setAttributes({globalAlpha: 0.5});
} else {
me.selectionRect.setAttributes({globalAlpha: 1});
}
surface.renderFrame();
return false;
}
}
Refer the source code for more details and understanding.
FYI: You may again have a question that you cannot start drawing your CrossZoom overlay outside the padding region. Check onGestureStart, if you are asking that question.

Determine if an open WPF window is visible on any monitor

Is there a way to determine if an open WPF window is currently visible in any of the desktop's connected monitors? By visible I mean that the window's bounds rectangle intersects with the desktop rectangle of any of the monitors.
I need this functionality to determine if a window needs to be repositioned because the monitor configuration (working areas bounds, monitor count) changed between restarts of my application (which saves window positions).
I have come up with the code below and it seems to work, but it has several problems:
I need to reference windows forms.
I need the desktop's DPI settings and transform the windows forms actual pixels to WPF virtual pixels.
I need an acutal Visual instance that already has been rendered to perform the transformation.
Do you know of a solution that gets rid of some or all of the 3 issues above?
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
internal static class Desktop
{
private static Size dpiFactor = new Size(1.0, 1.0);
private static bool isInitialized;
public static IEnumerable<Rect> WorkingAreas
{
get
{
return
Screen.AllScreens.Select(
screen =>
new Rect(
screen.WorkingArea.Left * dpiFactor.Width,
screen.WorkingArea.Top * dpiFactor.Height,
screen.WorkingArea.Width * dpiFactor.Width,
screen.WorkingArea.Height * dpiFactor.Height));
}
}
public static void TryInitialize(Visual visual)
{
if (isInitialized)
{
return;
}
var ps = PresentationSource.FromVisual(visual);
if (ps == null)
{
return;
}
var ct = ps.CompositionTarget;
if (ct == null)
{
return;
}
var m = ct.TransformToDevice;
dpiFactor = new Size(m.M11, m.M22);
isInitialized = true;
}
}
Usage of the (initialized) Desktop class:
private bool IsLocationValid(Rect windowRectangle)
{
foreach (var workingArea in Desktop.WorkingAreas)
{
var intersection = Rect.Intersect(windowRectangle, workingArea);
var minVisible = new Size(10.0, 10.0);
if (intersection.Width >= minVisible.Width &&
intersection.Height >= minVisible.Height)
{
return true;
}
}
return false;
}
Update
Using the virtual screen (SystemParameters.VirtualScreen*) does not work because when using multiple monitors the "desktop" is not a simple rectangle. It might be a polygon. There will be blind spots in the virtual screen because
the connected screens can have different resolutions
you can configure the position of each screen.
The code we use to do something similar uses information from SystemParameters, in particular SystemParameter.VirtualScreenLeft, Top, Width and Height.
If we have a saved Location and Size then we determine if the window is out of bounds like this:
bool outOfBounds =
(location.X <= SystemParameters.VirtualScreenLeft - size.Width) ||
(location.Y <= SystemParameters.VirtualScreenTop - size.Height) ||
(SystemParameters.VirtualScreenLeft +
SystemParameters.VirtualScreenWidth <= location.X) ||
(SystemParameters.VirtualScreenTop +
SystemParameters.VirtualScreenHeight <= location.Y);
I use this code snipped in my WPF project on startup; it's written in vb.net:
If My.Settings.RememberWindowPositionAndSize Then
If My.Settings.winMainWinState > 2 Then My.Settings.winMainWinState = WindowState.Normal
If My.Settings.winMainWinState = WindowState.Minimized Then My.Settings.winMainWinState = WindowState.Normal
Me.WindowState = My.Settings.winMainWinState
If My.Settings.winMainWinState = WindowState.Normal Then
Dim winBounds As New System.Drawing.Rectangle(CInt(My.Settings.winMainPosX), CInt(My.Settings.winMainPosY),
CInt(My.Settings.winMainSizeB), CInt(My.Settings.winMainSizeH))
For Each scr As System.Windows.Forms.Screen In System.Windows.Forms.Screen.AllScreens
If winBounds.IntersectsWith(scr.Bounds) Then
Me.Width = My.Settings.winMainSizeB
Me.Height = My.Settings.winMainSizeH
Me.Top = My.Settings.winMainPosY
Me.Left = My.Settings.winMainPosX
Exit For
End If
Next
End If
End If
and here is same (converted) code in C#
if (My.Settings.RememberWindowPositionAndSize) {
if (My.Settings.winMainWinState > 2)
My.Settings.winMainWinState = WindowState.Normal;
if (My.Settings.winMainWinState == WindowState.Minimized)
My.Settings.winMainWinState = WindowState.Normal;
this.WindowState = My.Settings.winMainWinState;
if (My.Settings.winMainWinState == WindowState.Normal) {
System.Drawing.Rectangle winBounds = new System.Drawing.Rectangle(Convert.ToInt32(My.Settings.winMainPosX), Convert.ToInt32(My.Settings.winMainPosY), Convert.ToInt32(My.Settings.winMainSizeB), Convert.ToInt32(My.Settings.winMainSizeH));
foreach (System.Windows.Forms.Screen scr in System.Windows.Forms.Screen.AllScreens) {
if (winBounds.IntersectsWith(scr.Bounds)) {
this.Width = My.Settings.winMainSizeB;
this.Height = My.Settings.winMainSizeH;
this.Top = My.Settings.winMainPosY;
this.Left = My.Settings.winMainPosX;
break;
}
}
}
}
This code checks if a window top left corner is inside the Virtual Screen box (the rectangle that includes all the available screens). It also takes care of multimonitor set ups where coordinates can be negative, for example primary monitor on the right or on the bottom.
bool valid_position =
SystemParameters.VirtualScreenLeft <= saved_location.X &&
(SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth) >= saved_location.X &&
SystemParameters.VirtualScreenTop <= saved_location.Y &&
(SystemParameters.VirtualScreenTop + SystemParameters.VirtualScreenHeight) >= saved_location.Y;

Resources