I have a QML application and need to open a dialog when I press a button. The dialog must be closed when the mouse is out of the dialog (with no click, so I think 'Popup' control can not be used).
For that, I use MouseAreas and control when the mouse is over one of my MouseAreas. I solved some problems (see QML: Problems with mousearea overlapping), but now I found another problem with a ScrollView (the dialog must contain a ScrollView with a ListView). I can not control when the mouse is over the scrollbar... And the dialog is closed since no MouseArea "has" the mouse over...
How can I control the mouse events on the scrollbar?
Thanks in advance,
Diego
Test.qml
import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Window 2.0
Item {
width: 800
height: 800
property bool m_bButtonHovered: false
onM_bButtonHoveredChanged: updateOpen()
Rectangle{
id: rect
anchors { top: parent.top; topMargin: 100; horizontalCenter: parent.horizontalCenter }
height: 50; width: 50
color: "red"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: m_bButtonHovered = true;
onExited: m_bButtonHovered = false;
}
}
Loader {
id: loader_dialog
anchors { top: rect.bottom; horizontalCenter: rect.horizontalCenter}
active: false
sourceComponent: TestMenu {
onClose: loader_dialog.active = false;
}
}
Timer {
id: timerOpen
interval: 200
running: false
repeat: false
onTriggered: checkOpen();
}
function updateOpen() {
if (m_bButtonHovered)
timerOpen.start();
}
function checkOpen(){
if (m_bButtonHovered)
loader_dialog.active = true;
}
}
TestMenu.qml
import QtQuick 2.0
import QtQuick.Controls 1.3
Rectangle {
id: id_dialog
signal close()
width: 400
height: 600
color: "lightgrey"
property int m_iNumHovered: 0
onM_iNumHoveredChanged: update();
function update() {
if (m_iNumHovered == 0)
timer.start();
}
function check() {
if (m_iNumHovered == 0)
id_dialog.close();
}
Timer {
id: timer
interval: 100
running: false
repeat: false
onTriggered: check();
}
MouseArea {
id: mouseAreaTopZone
anchors { bottom: parent.top; horizontalCenter: parent.horizontalCenter}
width: 50; height: 50
hoverEnabled: true
onEntered: m_iNumHovered++;
onExited: m_iNumHovered--;
}
MouseArea {
id: mouseAreaDialog
anchors.fill: parent
hoverEnabled: true
onEntered: m_iNumHovered++;
onExited: m_iNumHovered--;
}
ScrollView {
id: id_scrollView
anchors.centerIn: parent
height: 400; width: parent.width
ListView {
id: id_list
model: modelTest
anchors { left: parent.left; right: parent.right }
height: contentHeight
clip: true
interactive: false
delegate: Text {
height: 100
width: id_list.width
text: displayname
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
}
ListModel {
id: modelTest
ListElement { optionId: 1; displayname: "Option 1" }
ListElement { optionId: 2; displayname: "Option 2" }
ListElement { optionId: 3; displayname: "Option 3" }
ListElement { optionId: 4; displayname: "Option 4" }
ListElement { optionId: 5; displayname: "Option 5" }
ListElement { optionId: 6; displayname: "Option 6" }
ListElement { optionId: 7; displayname: "Option 7" }
}
}
Related
I am creating an image zoomIn/ZoomOut in ionic 5, hence the above error.
Below is my script:
HTML
<img #zoomedImage [src]="media.image" />
TS
#ViewChild('zoomedImage', { static: false }) zoomedImage: IonContent;
zoom = 1;
zoomIn() {
this.zoom += 0.1;
this.zoomedImage.nativeElement.style.transform = `scale(${this.zoom})`;
}
zoomOut() {
if (this.zoom > 1) {
this.zoom -= 0.1;
this.zoomedImage.nativeElement.style.transform = `scale(${this.zoom})`;
}
}
Because your using the wrong type in the viewChild. Use:
#ViewChild('zoomedImage', { static: false }) zoomedImage: ElementRef;
I'm using latest vue-chartjs package with vue3 to create stackbarchart. I've shown the stackbarchart on my app but it's labels are overlapping. I need to know which property can add in options that can fix my issue.
<template>
<Bar
v-if="chartData != null"
:key="id"
:data="chartData"
:options="chartOptions"
/>
</template>
<script>
import { Bar, getElementAtEvent } from "vue-chartjs";
import ChartJSPluginDatalabels from "chartjs-plugin-datalabels";
import uniqueId from "lodash.uniqueid";
import { drilldown } from "#/views/Reports/js/drilldown";
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
ArcElement
} from "chart.js";
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ArcElement,
ChartJSPluginDatalabels
);
export default {
name: "BarChartStacked",
components: {
Bar,
},
props: ["data", "options", "reportData", "eventInfo", "item", "duringDay"],
data() {
return {
id: null,
};
},
computed:{
chartData() { return this.data; /* mutable chart data */ },
chartOptions() { return this.options; /* mutable chart options */ }
},
mounted() {
this.id = uniqueId();
this.chartOptions.plugins.responsive = true;
if (this.reportData && this.reportData.dataFilter) {
if (this.item.conditions) {
// change cursor to pointer if element is clickable
this.chartOptions.hover = {
onHover: function(e) {
var point =getElementAtEvent(e);
if (point.length) e.target.style.cursor = 'pointer';
else e.target.style.cursor = 'default';
}
}
this.chartOptions.onClick = this.handle;
}
} else {
this.chartOptions.hover = {}
}
},
The stackbarchart should display value for the top most graph only like mention in the picture.
We're currently working on a Twitter-esque Client for SwiftUI and we have to convert HTML content to NSAttributedStrings. For that reason, we're using Atributika to style the HTML tags. It seems to be working correctly, but when we try to display the content, the text just goes over other content. We've assumed it is because it does not respect its parent's size, but it's probably something else.
How would we fix this? Is there a better way to render HTML content in SwiftUI that doesn't require using WKWebViews since that will result in an incredible performance drop?
Is there something we're missing?
Thanks in advance.
Our code:
NetworkView.swift
struct NetworkView: View {
#ObservedObject var timeline = NetworkViewModel()
private let size: CGFloat = 300
private let padding: CGFloat = 10
private let displayPublic: Bool = true
var body: some View {
List {
Section {
NavigationLink(destination: Text("F").padding()) {
Label("Announcements", systemImage: "megaphone")
}
NavigationLink(destination: Text("F").padding()) {
Label("Activity", systemImage: "flame")
}
}
.listStyle(InsetGroupedListStyle())
Section(header:
Picker(selection: self.$timeline.type, label: Text("Network visibility")) {
Text("My community").tag(TimelineScope.local)
Text("Public").tag(TimelineScope.public)
} .pickerStyle(SegmentedPickerStyle())
.padding(.top)
.padding(.bottom, 2)) {
if self.timeline.statuses.isEmpty {
HStack {
Spacer()
VStack {
Spacer()
ProgressView(value: 0.5)
.progressViewStyle(CircularProgressViewStyle())
Text("Loading posts...")
Spacer()
}
Spacer()
}
} else {
ForEach(self.timeline.statuses, id: \.self.id) { status in
StatusView(status: status)
.buttonStyle(PlainButtonStyle())
}
}
}
}
.listStyle(GroupedListStyle())
}
}
StatusView.swift
import SwiftUI
import Atributika
/// A structure that computes statuses on demand from a `Status` data model.
struct StatusView: View {
#if os(iOS)
#Environment(\.horizontalSizeClass) private var horizontalSizeClass
#endif
/// In Starlight, there are two ways to display mastodon statuses:
/// - Standard: The status is being displayed from the feed.
/// - Focused: The status is the main post of a thread.
///
/// The ``StatusView`` instance should know what way it is being
/// displayed so that it can display the content properly.
/// In order to achieve this, we pass a bool to ``StatusView``, which when true,
/// tells it that it's content should be displayed as `Focused`.
private var isMain: Bool
/// The ``Status`` data model whose the data will be displayed.
var status: Status
#if os(iOS)
/// Using for triggering the navigation View **only**when the user taps
/// on the content, and not when it taps on the action buttons.
#State var goToThread: Int? = 0
#State var showMoreActions: Bool = false
#State var profileViewActive: Bool = false
#endif
private let rootStyle: Style = Style("p")
.font(.systemFont(ofSize: 17, weight: .light))
private let rootPresentedStyle: Style = Style("p")
.font(.systemFont(ofSize: 20, weight: .light))
private func configureLabel(_ label: AttributedLabel, size: CGFloat = 17) {
label.numberOfLines = 0
label.textColor = .label
label.font = .systemFont(ofSize: size)
label.lineBreakMode = .byWordWrapping
}
/// To easily use the same view on multiple platforms,
/// we use the `body` view as a container where we load platform-specific
/// modifiers.
var body: some View {
// We use this vertical stack to load platform specific modifiers,
// or to load specific views when a condition is met.
VStack {
// Whether the post is focused or not.
if self.isMain {
self.presentedView
} else {
// To provide the best experience, we want to allow the user to easily
// interact with a post directly from the feed. Because of that, we need
// to add a button
ZStack {
self.defaultView
NavigationLink(
destination: ThreadView(mainStatus: self.status),
tag: 1,
selection: self.$goToThread,
label: {
EmptyView()
}
)
}
}
}
.buttonStyle(PlainButtonStyle())
}
/// The status display mode when it is the thread's main post.
var presentedView: some View {
VStack(alignment: .leading) {
NavigationLink(destination:
ProfileView(isParent: false,
accountInfo: ProfileViewModel(accountID: self.status.account.id),
onResumeToParent: {
self.profileViewActive = false
}),
isActive: self.$profileViewActive) {
EmptyView()
}
HStack(alignment: .center) {
ProfileImage(from: self.status.account.avatarStatic, placeholder: {
Circle()
.scaledToFit()
.frame(width: 50, height: 50)
.foregroundColor(.gray)
})
VStack(alignment: .leading, spacing: 5) {
VStack(alignment: .leading) {
Text("\(self.status.account.displayName)")
.font(.headline)
Text("\(self.status.account.acct)")
.foregroundColor(.gray)
.lineLimit(1)
}
}
Spacer()
Button(action: { self.showMoreActions.toggle() }, label: {
Image(systemName: "ellipsis")
.imageScale(.large)
})
}
GeometryReader { (geometry: GeometryProxy) in
AttributedTextView(attributedText:
"\(self.status.content)"
.style(tags: rootPresentedStyle),
configured: { label in configureLabel(label, size: 20) },
maxWidth: geometry.size.width)
.fixedSize(horizontal: true, vertical: true)
}
if !self.status.mediaAttachments.isEmpty {
AttachmentView(from: self.status.mediaAttachments[0].url) {
Rectangle()
.scaledToFit()
.cornerRadius(10)
}
}
HStack {
Text("\(self.status.createdAt.getDate()!.format(as: "hh:mm · dd/MM/YYYY")) · ")
Button(action: {
if let application = self.status.application {
if let website = application.website {
openUrl(website)
}
}
}, label: {
Text("\(self.status.application?.name ?? "Mastodon")")
.lineLimit(1)
})
.foregroundColor(.accentColor)
.padding(.leading, -7)
}
.padding(.top)
Divider()
Text("\(self.status.repliesCount.roundedWithAbbreviations) ").bold()
+
Text("comments, ")
+
Text("\(self.status.reblogsCount.roundedWithAbbreviations) ").bold()
+
Text("boosts, and ")
+
Text("\(self.status.favouritesCount.roundedWithAbbreviations) ").bold()
+
Text("likes.")
Divider()
self.actionButtons
.padding(.vertical, 5)
.padding(.horizontal)
}
.buttonStyle(PlainButtonStyle())
.navigationBarHidden(self.profileViewActive)
.actionSheet(isPresented: self.$showMoreActions) {
ActionSheet(title: Text("More Actions"),
buttons: [
.default(Text("View #\(self.status.account.acct)'s profile"), action: {
self.profileViewActive = true
}),
.destructive(Text("Mute #\(self.status.account.acct)"), action: {
}),
.destructive(Text("Block #\(self.status.account.acct)"), action: {
}),
.destructive(Text("Report #\(self.status.account.acct)"), action: {
}),
.cancel(Text("Dismiss"), action: {})
]
)
}
}
var defaultView: some View {
VStack(alignment: .leading) {
Button(action: {
self.goToThread = 1
}, label: {
HStack(alignment: .top) {
ProfileImage(from: self.status.account.avatarStatic, placeholder: {
Circle()
.scaledToFit()
.frame(width: 50, height: 50)
.foregroundColor(.gray)
})
VStack(alignment: .leading, spacing: 5) {
HStack {
HStack(spacing: 5) {
Text("\(self.status.account.displayName)")
.font(.headline)
.lineLimit(1)
Text("\(self.status.account.acct)")
.foregroundColor(.gray)
.lineLimit(1)
Text("· \(self.status.createdAt.getDate()!.getInterval())")
.lineLimit(1)
}
}
GeometryReader { (geometry: GeometryProxy) in
AttributedTextView(attributedText:
"\(self.status.content)"
.style(tags: rootStyle),
configured: { label in configureLabel(label, size: 17) },
maxWidth: geometry.size.width)
.fixedSize(horizontal: true, vertical: false)
}
if !self.status.mediaAttachments.isEmpty {
AttachmentView(from: self.status.mediaAttachments[0].previewURL) {
Rectangle()
.scaledToFit()
.cornerRadius(10)
}
}
}
}
})
self.actionButtons
.padding(.leading, 60)
}
.contextMenu(
ContextMenu(menuItems: {
Button(action: {}, label: {
Label("Report post", systemImage: "flag")
})
Button(action: {}, label: {
Label("Report \(self.status.account.displayName)", systemImage: "flag")
})
Button(action: {}, label: {
Label("Share as Image", systemImage: "square.and.arrow.up")
})
})
)
}
/// The post's action buttons (favourite and reblog), and also the amount of replies.
///
/// If the post is focused (``isMain`` is true), the count is hidden.
var actionButtons: some View {
HStack {
HStack {
Image(systemName: "text.bubble")
if !self.isMain {
Text("\(self.status.repliesCount.roundedWithAbbreviations)")
}
}
Spacer()
Button(action: {
}, label: {
HStack {
Image(systemName: "arrow.2.squarepath")
if !self.isMain {
Text("\(self.status.reblogsCount.roundedWithAbbreviations)")
}
}
})
.foregroundColor(
labelColor
)
Spacer()
Button(action: {
}, label: {
HStack {
Image(systemName: "heart")
if !self.isMain {
Text("\(self.status.favouritesCount.roundedWithAbbreviations)")
}
}
})
.foregroundColor(
labelColor
)
Spacer()
Button(action: {
}, label: {
Image(systemName: "square.and.arrow.up")
})
.foregroundColor(
labelColor
)
}
}
}
extension StatusView {
/// Generates a View that displays a post on Mastodon.
///
/// - Parameters:
/// - isPresented: A boolean variable that determines whether
/// the status is being shown as the main post (in a thread).
/// - status: The identified data that the ``StatusView`` instance uses to
/// display posts dynamically.
public init(isMain: Bool = false, status: Status) {
self.isMain = isMain
self.status = status
}
}
struct StatusView_Previews: PreviewProvider {
#ObservedObject static var timeline = NetworkViewModel()
static var previews: some View {
VStack {
if self.timeline.statuses.isEmpty {
HStack {
Spacer()
VStack {
Spacer()
ProgressView(value: 0.5)
.progressViewStyle(CircularProgressViewStyle())
Text("Loading status...")
Spacer()
}
Spacer()
}
.onAppear {
self.timeline.fetchLocalTimeline()
}
} else {
StatusView(isMain: false, status: self.timeline.statuses[0])
}
}
.frame(width: 600, height: 300)
.previewLayout(.sizeThatFits)
}
}
AttributedTextView.swift
import UIKit
import SwiftUI
import Foundation
import Atributika
// Note: Implementation pulled from pending PR in Atributika on GitHub: https://github.com/psharanda/Atributika/pull/119
// Credit to rivera-ernesto for this implementation.
/// A view that displays one or more lines of text with applied styles.
struct AttributedTextView: UIViewRepresentable {
typealias UIViewType = RestrainedLabel
/// The attributed text for this view.
var attributedText: AttributedText?
/// The configuration properties for this view.
var configured: ((AttributedLabel) -> Void)?
#State var maxWidth: CGFloat = 300
public func makeUIView(context: UIViewRepresentableContext<AttributedTextView>) -> RestrainedLabel {
let new = RestrainedLabel()
configured?(new)
return new
}
public func updateUIView(_ uiView: RestrainedLabel, context: UIViewRepresentableContext<AttributedTextView>) {
uiView.attributedText = attributedText
uiView.maxWidth = maxWidth
}
class RestrainedLabel: AttributedLabel {
var maxWidth: CGFloat = 0.0
open override var intrinsicContentSize: CGSize {
sizeThatFits(CGSize(width: maxWidth, height: .infinity))
}
}
}
Everything is working fine except scrolling when i click to the next element is taking their but is not scrolling to down for seeing purpose I have to scroll to down. I tried many ways but i could not able to fix please help me to fix this problem i gone through this link https://www.npmjs.com/package/angular-shepherd but no option . If anyone can help me that would be very great help for me.
<h2 class="second-element">London</h2>
<p class="third-element">London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<div class="first-element">cool</div>
I have added this in my app.component.ts file code..
import { ShepherdService } from 'angular-shepherd';
export class AppComponent implements AfterViewInit {
constructor(private shepherdService: ShepherdService) { }
ngAfterViewInit() {
this.shepherdService.disableScroll = true;
this.shepherdService.modal = true;
this.shepherdService.confirmCancel = false;
this.shepherdService.addSteps([
{
id: 'intro',
options: {
attachTo: '.first-element bottom',
beforeShowPromise: function() {
return new Promise(function(resolve) {
setTimeout(function() {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Exit',
type: 'cancel'
},
{
classes: 'shepherd-button-primary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
classes: 'custom-class-name-1 custom-class-name-2',
highlightClass: 'highlight',
scrollTo: true,
showCancelLink: true,
title: 'Welcome to Rivet Labs',
text: ['This will help you toggle sidebar menu'],
when: {
show: () => {
console.log('show step');
},
hide: () => {
console.log('hide step');
}
}
}
},
{
here is 2nd id goes here
},
{
here is 3rd id goes here
}
}
I have solve my problem just we need to remove scroll function from next id to get to the element in default position. we have to remove this property //beforeShowPromise:function(){}// for next id.
beforeShowPromise: function() {
return new Promise(function(resolve) {
setTimeout(function() {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},
I have an array of objects that contain emp info like name age etc and I have a page with previous and next buttons. I want to be able to navigate to the object in the array after clicking on the next button. Do I need use something like redux to achieve this or is there another way to do this. Is there a way to do this in polymer directly.
<dom-module id="my-quiz">
<template>
<div>Employee List</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>
</template>
<script>
class Quiz extends Polymer.Element {
static get is() { return 'my-quiz'; }
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
prev() {
console.log("prev");
}
next() {
console.log("next");
}
}
window.customElements.define(Quiz.is, Quiz);
</script>
</dom-module>
Here an example how to do this. There may other ways too. :
<div>Employee ID: [[_calculateId(index)]] Name: [[_calculateName(index)]]</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>on>
</template>
<script>
class MyTest extends Polymer.Element {
static get is() { return 'my-test'; }
static get properties() { return {
index:{
type:Number,
value:0
}
}}
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
_calculateName(i) { return this.employees[i].name }
_calculateId (i) { return this.employees[i].id }
prev() {
console.log("prev");
if (this.index>0) { this.index -= 1 }
}
next() {
console.log("next");
if (this.index < this.employees.length-1){this.index +=1}
}
}
customElements.define(MyTest.is, MyTest);
Demo