Offset position of "close button" in Three20 TTLauncherView - three20

I'm using the Three20 library to create a TTLauncherView in an iPhone app that I'm working on. When the user touches and holds on one of the items in the launcher view it causes all the items to start wiggling and an "x" button to appear in the top left corner of the of each item image. This button is used to remove items from the launcher view. I would like to move this "x" button a little down and to the right relative to the item image.
I have looked at TTDeafaultStyleSheet andfound the following code:
///////////////////////////////////////////////////////////////////////////////////////////////////
- (TTStyle*)launcherCloseButtonImage:(UIControlState)state {
return
[TTBoxStyle styleWithMargin:UIEdgeInsetsMake(-2, 0, 0, 0) next:
[TTImageStyle styleWithImageURL:nil defaultImage:nil contentMode:UIViewContentModeCenter
size:CGSizeMake(10,10) next:nil]];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (TTStyle*)launcherCloseButton:(UIControlState)state {
return
[TTShapeStyle styleWithShape:[TTRoundedRectangleShape shapeWithRadius:TT_ROUNDED] next:
[TTInsetStyle styleWithInset:UIEdgeInsetsMake(1, 1, 1, 1) next:
[TTShadowStyle styleWithColor:RGBACOLOR(0,0,0,0.5) blur:2 offset:CGSizeMake(0, 3) next:
[TTSolidFillStyle styleWithColor:[UIColor blackColor] next:
[TTInsetStyle styleWithInset:UIEdgeInsetsMake(-1, -1, -1, -1) next:
[TTSolidBorderStyle styleWithColor:[UIColor whiteColor] width:2 next:
[TTPartStyle styleWithName:#"image" style:TTSTYLE(launcherCloseButtonImage:) next:
nil]]]]]]];
}
This code touches the "x" button, but I haven't been able to figure out how to change its position. Does anyone have any suggestions?

I was unable to figure our how to move the close button in the way that I wanted using the code in my question, but I did find where to adjust the position of the button by editing the Three20 file TTLauncherButton.m. In the -(void)layoutSubviews method I adjusted the origin of the _closeButton property.

Related

How can I get a borderless child window to re-scale to current screen in multi-monitor setup?

My app has a main window which creates and opens an instance of a subclass of a QML Window {} using createObject(). This window has its flags: set to be a borderless window (I've added code so that it can be grabbed and dragged around).
When I attach a monitor to my laptop and set its font scale factor to 125% (or 150%), when I drag my main window over to the second monitor, you can see it suddenly "snap" to the larger size when it reaches the halfway point. Likewise, when I drag it back to my laptop screen it again "snaps" to the smaller size when I get halfway over (this behavior is what I want, so no problems here).
My problem is that when I drag my created borderless window over into the monitor, it keeps the original 100% scale factor and does not "snap" to a larger size. If I drag my main window over to the monitor, it gets larger but the borderless window remains at the smaller scale; only when I grab the borderless window and move it slightly does it suddenly "snap" to the larger scale size. The same thing happens in reverse - if I then drag the borderless window back onto the laptop, it remains at the larger size until I drag the main window back over and then move the borderless window slightly (at which point it suddenly "snaps" to the smaller size).
So it appears that this created Window uses the scale factor of the screen that the parent window window that created it is currently in, even if it is in a different screen itself.
Is this happening because the Window is borderless? (I'm about to test this but my build process is incredibly slow) Or is there any way to set this borderless Window up so that it detects that it is crossing into a new screen and re-scales itself (in the same way that my main window does)?
Update: I just ran a test giving my Window a native titlebar, and with a titlebar the window instantly adopts ("snaps to") the scale factor of whichever screen it happens to be in, just like my main window (and independent of the main window's scale factor).
So is there any way to duplicate this auto-scaling window behavior with a borderless window? Some flag I need to call, or some method(s) I need to call to get the OS to rescale the window?
Update 2: I tried out Felix's SetWindowPos solution. It does move the window, but this does not fix the scaling problem - the behavior of the frameless window is the same and it still does not correctly pick up the scaling factor of the screen it is in.
I am running a test using MoveWindow instead of SetWindowPos to see if that affects anything [edit: MoveWindow does not work, either - same problem]. Then I'm going to try SendMessage or PostMessage along with NoBugz' suggestion of the WM_DPICHANGED message.
Any other suggestions are welcome.
Update 3: I just created a quick C# app (winforms) to see if the same problem occurs with that, and it doesn't - when a borderless form in the C# app is dragged over into the other monitor, it immediately picks up the scale factor change. So it appears this is a Qt problem.
Update 4: See my answer below for a working solution to this problem (if a bit of a hack).
So as far as I understand, your current goal is to move the window via the WIN-API.
You will have to do so via C++. The approach would be:
Pass the QML Window to a C++-Method exposed to QML as a QQuickWindow (The QML window instanciates that type, as seen in the documentation)
Use QWindow::winId to get the native HWND
Call the SetWindowPos WIN-API method to move it
Code sample (C++-part):
// the method
void moveWindow(QQuickWindow *window, int x, int y) {
HWND handle = (HWND)window->winId();
Q_ASSERT(handle);
::SetWindowPos(handle, HWND_TOP,
x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
}
// assuming "moveWindow" is a member of "MyClass"
qmlEngine->rootContext()->setContextProperty("mover", new MyClass(qmlEngine));
Code sample (QML-part):
// call this method as soon as the drag has finished, with the new positions
mover.moveWindow(idOfWindow, xPos, yPos);
Note: I would recommend you try out calling this only after the drag was finished (and move the window as you do right now until then). If that works, you can try out what happens if you call this during the drag instead of changing the x/y of the window.
I figured out a relatively simple way to fix this problem. Since a frameless window in Qt gets its scaling factor from the window that created it, the trick is to create another window (that has a titlebar but is not visible to the user) and create the frameless window there, and then add code to the frameless window to keep the hidden window positioned underneath it as the user drags it. When the frameless window is dragged into another screen, the hidden window goes with it, picks up the new scale factor (since it has a titlebar) and then the frameless window immediately gets the new screen's scale factor as well.
Here is sample solution code:
// HiddenWindow.qml
Window {
id: hiddenWindow
// note: just making window visible: false does not work.
opacity: 0
visible: true
flags: Qt.Tool | Qt.WindowTitleHint | Qt.WindowTransparentForInput |
Qt.WindowStaysOnTopHint // Qt.Tool keeps this window out of the
// taskbar
function createVisibleWindow() {
var component = Qt.createComponent("VisibleWindow.qml")
if (component.status === Component.Ready) {
var win = component.createObject(hiddenWindow)
return win
}
}
}
// VisibleWindow.qml
Window {
id: visibleWindow
property var creatorWindow: undefined
flags: Qt.FramelessWindowHint
onXChanged: {
creatorWindow.x = x
}
onYChanged: {
creatorWindow.y = y
}
onWidthChanged: {
creatorWindow.width = width
}
onHeightChanged: {
creatorWindow.height = height
}
}
And then to use these classes from your main window QML:
property var hiddenWindow: undefined
property var visibleWindow: undefined
Component.onCompleted: {
var component = Qt.createComponent("HiddenWindow.qml")
if (component.status === Component.Ready) {
hiddenWindow = component.createObject(null)
}
visibleWindow = hiddenWindow.createVisibleWindow()
visibleWindow.creatorWindow = hiddenWindow
visibleWindow.show()
}
You need to resize window when window move to other screen
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onPressed: {
movePos = Qt.point(mouse.x, mouse.y)
isDoubleClicked = false
lastWindowWidth = mainWindow.width
lastWindowHeight = mainWindow.height
}
onPositionChanged: {
if (!isDoubleClicked) {
const delta = Qt.point(mouse.x - movePos.x, mouse.y - movePos.y)
if (mainWindow.visibility !== Window.Maximized) {
mainWindow.x = mainWindow.x + delta.x
mainWindow.y = mainWindow.y + delta.y
mainWindow.width = lastWindowWidth
mainWindow.height = lastWindowHeight
}
}
}
}

Xcode Playground Timeline empty

I am trying to use the timeline assistant editor for playground in xcode version 7.3.1, it is always empty.
Timeline assistant editor
I think the error is from xcode, however from search it doesn't look like anyone got the same error so i am confused.
To display the result of print you need to open the "debug area" by going to menu
View > Debug Area > Show Debug Area
or click on the button in the lower left part:
To display the timeline graph, you could use XCPCaptureValue:
import XCPlayground
var x = 0
for i in 0...10 {
x += i
print(x)
XCPCaptureValue("Value for x", value: x)
}
but XCPCaptureValue has been deprecated and won't be available in the future (there's no available replacement).
The alternative is to display the graph inline by clicking on the "+" button on the right:
Do a right click on the graphs and you can choose to display value history instead:
I was just getting started in Playgrounds myself, and came across the same problem of not being able to print to Timeline.
This Medium article explains how to show or render things in the timeline as of Xcode 8 and Swift 3. Basically, you have to create a view and assign it to the PlaygroundPage.current.liveView:
import UIKit
import PlaygroundSupport
let contentView = UIView(frame: CGRect(x: 0, y: 0, width: 320.0, height: 600.0))
contentView.backgroundColor = UIColor.white
PlaygroundPage.current.liveView = contentView
Afterwards, you can add anything to your contentView to be displayed in the timeline. The PlaygroundPage.current.liveView can receive any UIView, such as UILabel, UITextField, etc.
However, sometimes the created view defaults to a black background, so you have to remember to set the .backgroundColor to UIColor.white to see it's info/child views.

How to get rect of the item in Listbox using winapi

I am using VC6.0. I am trying programming to show contextmenu when I right click on the item of the ListBox. But now the popmenu can show anywhere in the rect of ListBox, since I only can get the rect of the ListBox, and I dont know how to get the rect of the item. I know that there is a macro ListView_GetSubItemRect which seems to get the rect of item of ListView. Is there similar way for ListBox, or is there a way to get the width and the height of item of ListBox, so I can caculate the rect? I didnt find some useful information on msdn and google? Can anyone give me some ideas? Thanks.
My current Code:
void My_OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos)
{
HWND hList = GetDlgItem(hwnd,IDC_LIST_RESTYPE);
if (hList == hwndContext)
{
if(-1!=indexLB)
{
RECT rect;
POINT pt;
GetClientRect(hwndContext, &rect);
ScreenToClient(hwndContext, &pt);
if(PtInRect(&rect, pt))
{
HMENU hroot = LoadMenu((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU_DELTYPE));
if(hroot)
{
HMENU hpop = GetSubMenu(hroot,0);
ClientToScreen(hwndContext, &pt);
TrackPopupMenu(hpop, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwndContext, NULL);
DestroyMenu(hroot);
}
}
}
}
}
Edit
Current:
First, I left click an item to selected、 an item. And Second I right click the selected item to show popmenu. It shows normally. But in the second step if I click the blank area of ListBox, it shows menu either. That is not what I expected.
What I expected is:
The menu only shows when I click an item and the position only over the item. When I right click other area, it wont be showed.
You are looking for the ListBox_GetItemRect macro.
However, I do feel that the user will find it odd to click in one place and see the menu appear somewhere else.
The proper solution to this problem is to popup the context menu at the mouse position. Clicking in one place and popping it up somewhere else would be very bad.
To get the mouse position use GetCursorPos().
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648390%28v=vs.85%29.aspx
To be clear, first use ListBox_GetItemRect to work out which item is clicked on, and ignore it if none. Then use GetCursorPos so the menu appears exactly where the mouse is -- inside the list item -- and not somewhere a few pixels away. The Windows UI standards are that the context menu appears at the cursor position.
I'm not sure Why you wrote your own OnContextMenu - you should use the class wizard to map WM_CONTEXTMENU with the standard handler where the existing function ends up in your code like this:
//Wizard Added this the message map block
ON_WM_CONTEXTMENU()
//Declares the function with the proper parameters
void MyDlg::OnContextMenu(CWnd* pWnd, CPoint point);
//in the body of OnContextMenu use the system supplied parameters and the
//menu will appear next to the mouse position wherever it is clicked in the control
CMenu popupmenu;
popupmenu.LoadMenu(IDR_RMOUSEPOPUP);
int Command = (int)popupmenu.GetSubMenu(0)->TrackPopupMenu(
TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY,
point.x, point.y, pWnd);

UITableView - Section header's disclosure button changes randomly

I'm trying to make my own table view displaying hierarchical data based on Apple's "Table View Animations and Gestures" sample code.
Everything works fine in Apple's demo, until I add more root items than it is displayable on the screen.
Problem is that if I expand first root item and scroll down, the disclosure button of last root item displays expanded state.
Then if I scroll to the top (sometimes it needs to be repeated few times), the disclosure button of first item already shows collapsed state but the item is still expanded.
If I click to such item the app crashes with error:
'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'
I have copied the sample code from here:
https://developer.apple.com/library/ios/samplecode/tableviewupdates/TableViewUpdates.zip
Data source is "PlaysAndQuotations.plist" and it has been changed following:
Copy all 3 root dict items (also with their array of dicts) 4 times, so it contains 12 root items with all their subitems.
My adapted Plist data file can be downloaded here:
https://drive.google.com/file/d/0B__nLmZ1h_-eUHVlTV9FbzN2aGc/edit?usp=sharing
Please help me to find out, why is the disclosure button changing its state by itself and how to fix the crashes.
This has solved the issue
(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
Add the following :
if (section == self.openSectionIndex ){
sectionHeaderView.disclosureButton.selected = YES;
}
else
sectionHeaderView.disclosureButton.selected = NO;
APLSectionHeaderView
- (void)toggleOpenWithUserAction:(BOOL)userAction {
// Comment this line self.disclosureButton.selected = !self.disclosureButton.selected;
if (userAction) {
// toggle the disclosure button state
self.disclosureButton.selected = !self.disclosureButton.selected; //Add here

Edit Control showing a readout of Slider Control's position

I have created a Slider Control and an Edit Control that are linked, so that moving the slider changes the edit box's text, and manually editing the text moves the slider. For the most part it works but after I release the mouse button when dragging the Slider, the Edit Control shows 0. While I'm dragging it does show the correct value.
I can partially fix the problem by adding an if(nPos != 0) clause, which stops that happening. However when I click to move the Slider rather than drag, the Edit Control doesn't update.
Do I need a different handler for when the Slider is clicked rather than dragged? Or am I doing something wrong?
// Updates slider when value is changed in the Edit Box
void CProject1Dlg::OnChangeEdit1() {
SLIDER_1.SetPos(GetDlgItemInt(IDC_EDIT1) / 1000);
}
// Slider horizontal scroll handler
void CProject1Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (nPos != 0) {
SetDlgItemInt(IDC_EDIT1, nPos * 1000);
}
CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}
What happens if you try extracting the position of the slider directly with GetPos rather than using the nPos parameter?

Resources