Treeviews QueueDraw doesn't render current row? - mono

I'm working with a treeview, which contains several columns, also one displaying a pixbuf, if audio is playing or paused. If the user double clicks on one row, audio playback starts and the row needs to be rerendered in order to display the pixbuf icon. I used QueueDraw for this, but that does only work, if the cursor leaves the current row. How can I update the pixbuf directly?
CODE:
protected void trvMainCuesheetRowActivated (object o, RowActivatedArgs args)
{
log.debug("trvMainCuesheetRowActivated called");
TreeIter ti = TreeIter.Zero;
this.lsCuesheetData.GetIter(out ti,args.Path);
if (this.lsCuesheetData.GetValue(ti,0) != null)
{
Track tCurTrack = (Track)this.lsCuesheetData.GetValue(ti,0);
if (this.objProgram.getAudioManager().getPlayState() == AudioCuesheetEditor.AudioBackend.PlayState.Stopped)
{
this.objProgram.getAudioManager().play(tCurTrack);
this.refresh();
}
else
{
if (this.objProgram.getAudioManager().getPlayState() == AudioCuesheetEditor.AudioBackend.PlayState.Playing)
{
this.objProgram.getAudioManager().seek(tCurTrack);
this.refresh();
}
}
}
}
private void renderPlaying(TreeViewColumn _tvcColumn, CellRenderer _crCell, TreeModel _tmModel, TreeIter _tiIter)
{
Track tCurTrack = (Track)_tmModel.GetValue (_tiIter, 0);
//Just display an icon, if we are playing
if (this.objProgram.getAudioManager().getPlayState() == AudioCuesheetEditor.AudioBackend.PlayState.Playing)
{
if (this.objProgram.getAudioManager().getCurrentlyPlayingTrack() == tCurTrack)
{
Gdk.Pixbuf icon = this.RenderIcon(Stock.MediaPlay, IconSize.SmallToolbar, null);
(_crCell as CellRendererPixbuf).Pixbuf = icon;
}
else
{
(_crCell as CellRendererPixbuf).Pixbuf = null;
}
}
else
{
if (this.objProgram.getAudioManager().getPlayState() == AudioCuesheetEditor.AudioBackend.PlayState.Paused)
{
if (this.objProgram.getAudioManager().getCurrentlyPlayingTrack() == tCurTrack)
{
Gdk.Pixbuf icon = this.RenderIcon(Stock.MediaPause, IconSize.SmallToolbar, null);
(_crCell as CellRendererPixbuf).Pixbuf = icon;
}
else
{
(_crCell as CellRendererPixbuf).Pixbuf = null;
}
}
else
{
(_crCell as CellRendererPixbuf).Pixbuf = null;
}
}
}
//Purpose: Function used to refresh the MainWindow depending on new options set.
public void refresh()
{
//QueueDraw is needed since it fires a signal to cellrenderers to update
this.trvMainCuesheet.QueueDraw();
this.sbMainWindow.Visible = this.objProgram.getObjOption().getBShowStatusbar();
this.mwToolbar.Visible = this.objProgram.getObjOption().getBToolbarVisible();
}
Greetings
Sven

Found the error myself.
this.objProgram.getAudioManager().getCurrentlyPlayingTrack()
didn't always return a track, where I expected one, so the renderer worked right. Bug is fixed, thanks anyway ;).

Related

How to move the snap position from center to left of RecycleView using SnapHelper?

I have an RecycleView that contains ImageViews and my question is how can i move the snap to be on the left side of the RecycleView instead of the center?
When i move the ImageViews they get snapped in the center and I can move them to the left or right inside that "snap window" by overriding the CalculateDistanceToFinalSnap method. I think I would now need to move that "snap window" to the left side of the RecycleView but I don't know how, or maybe there is another way, please help.
Here is a image of my problem, maybe it will help you to understand more clearly:
image
#Jessie Zhang -MSFT's solution works for me. The code was a little oddly formatted and I had some difficulty bringing it over. Here is the same solution (for a horizontal snap only) in Kotlin.
class StartSnapHelper: LinearSnapHelper() {
override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray? {
return if (layoutManager.canScrollHorizontally()) {
val outer = mutableListOf<Int>()
outer.add(distanceToStart(targetView, getHorizontalHelper(layoutManager)))
outer.add(0)
outer.toIntArray()
} else {
super.calculateDistanceToFinalSnap(layoutManager, targetView)
}
}
override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
return if (layoutManager is LinearLayoutManager) {
if (layoutManager.canScrollHorizontally()) {
getStartView(layoutManager, getHorizontalHelper(layoutManager))
} else {
super.findSnapView(layoutManager)
}
} else {
super.findSnapView(layoutManager)
}
}
private fun distanceToStart(targetView: View, helper: OrientationHelper): Int {
return helper.getDecoratedStart(targetView) - helper.startAfterPadding
}
private fun getStartView(layoutManager: RecyclerView.LayoutManager, orientationHelper: OrientationHelper): View? {
val firstChild = (layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val isLastItem = (layoutManager.findLastCompletelyVisibleItemPosition() == layoutManager.itemCount - 1)
if (firstChild == RecyclerView.NO_POSITION || isLastItem) {
return null
}
val child = layoutManager.findViewByPosition(firstChild)
return if (orientationHelper.getDecoratedEnd(child) >= orientationHelper.getDecoratedMeasurement(child) / 2
&& orientationHelper.getDecoratedEnd(child) > 0) {
child;
} else {
if (layoutManager.findFirstCompletelyVisibleItemPosition() == layoutManager.itemCount -1) {
null
} else {
layoutManager.findViewByPosition(firstChild + 1)
}
}
}
private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
return OrientationHelper.createHorizontalHelper(layoutManager)
}
}
I have achieved this function ,we juse need to create a class and extent class LinearSnapHelper and override method CalculateDistanceToFinalSnap and FindSnapView. You can check out the full demo here .
The main code is as follows:
public class StartSnapHelper: LinearSnapHelper
{
private OrientationHelper mVerticalHelper, mHorizontalHelper;
public StartSnapHelper()
{
}
public override void AttachToRecyclerView(RecyclerView recyclerView)
{
base.AttachToRecyclerView(recyclerView);
}
public override int[] CalculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView)
{
//return base.CalculateDistanceToFinalSnap(layoutManager, targetView);
int[] outer = new int[2];
if (layoutManager.CanScrollHorizontally())
{
outer[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
} else {
outer[0] = 0;
}
if (layoutManager.CanScrollVertically()) {
outer[1] = distanceToStart(targetView, getVerticalHelper(layoutManager));
} else {
outer[1] = 0;
}
return outer;
}
private int distanceToStart(View targetView, OrientationHelper helper)
{
return helper.GetDecoratedStart(targetView) - helper.StartAfterPadding;
}
public override View FindSnapView(RecyclerView.LayoutManager layoutManager)
{
if (layoutManager is LinearLayoutManager) {
if (layoutManager.CanScrollHorizontally())
{
return getStartView(layoutManager, getHorizontalHelper(layoutManager));
}
else
{
return getStartView(layoutManager, getVerticalHelper(layoutManager));
}
}
return base.FindSnapView(layoutManager);
}
private View getStartView(RecyclerView.LayoutManager layoutManager,
OrientationHelper helper)
{
if (layoutManager is LinearLayoutManager) {
int firstChild = ((LinearLayoutManager)layoutManager).FindFirstVisibleItemPosition();
bool isLastItem = ((LinearLayoutManager)layoutManager)
.FindLastCompletelyVisibleItemPosition()
== layoutManager.ItemCount - 1;
if (firstChild == RecyclerView.NoPosition || isLastItem)
{
return null;
}
View child = layoutManager.FindViewByPosition(firstChild);
if (helper.GetDecoratedEnd(child) >= helper.GetDecoratedMeasurement(child) / 2
&& helper.GetDecoratedEnd(child) > 0)
{
return child;
}
else
{
if (((LinearLayoutManager)layoutManager).FindLastCompletelyVisibleItemPosition()
== layoutManager.ItemCount - 1)
{
return null;
}
else
{
return layoutManager.FindViewByPosition(firstChild + 1);
}
}
}
return base.FindSnapView(layoutManager);
}
private OrientationHelper getVerticalHelper(RecyclerView.LayoutManager layoutManager)
{
if (mVerticalHelper == null)
{
mVerticalHelper = OrientationHelper.CreateVerticalHelper(layoutManager);
}
return mVerticalHelper;
}
private OrientationHelper getHorizontalHelper(RecyclerView.LayoutManager layoutManager)
{
if (mHorizontalHelper == null)
{
mHorizontalHelper = OrientationHelper.CreateHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}
And use like this:
SnapHelper snapHelperStart = new StartSnapHelper();
snapHelperStart.AttachToRecyclerView(recyclerView);

wxwidget - issue of wxEVT_LEAVE_WINDOW event

I'd like to implement a card style UI(as the screen shot), card is using a wxPanel as a container, a static text and a static bmp in the panel. the card will zoom in and color changed when mouse on it, when the mouse leave the card, size and color will recover as normal state. I add some logic in onEnter and onLeave of wxPanel to handle zoom and color change. the card works fine in most of cases, but if mouse move quickly, multiple cards will be selected. From output log, it seems the issue happens in OnLeave, !GetClientRect().Contains(event.GetPosition()) = false, even the mouse actually has been out of the rect of the card. how can the card work as expected even mouse move quickly?
enter image description here
void TypeCard::OnEnter(wxMouseEvent& event) {
wxRect rect = GetClientRect();
wxPoint pnt = event.GetPosition();
TRACELOG_WARNING("###### On Enter left=%d top=%d width=%d height=%d", rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
TRACELOG_WARNING("&&&&&& On Enter x=%d y=%d", pnt.x, pnt.y);
if (GetClientRect().Contains(event.GetPosition()) && !selected_ ) {
TRACELOG_WARNING("&&&&&&On Enter = true");
if (m_bZoomEnabled) {
ZoomCard(zoom_in, 5, 5);
}
selected_ = true;
} else {
TRACELOG_WARNING("*****************************************************On Enter = false selected_ = %d", (int)selected_ );
}
// have_focus_ = true;
Refresh(false);
Update();
event.Skip();
}
void TypeCard::OnLeave(wxMouseEvent& event) {
wxRect rect = GetClientRect();
wxPoint pnt = event.GetPosition();
TRACELOG_WARNING("###### On OnLeave left=%d top=%d width=%d height=%d", rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
TRACELOG_WARNING("&&&&&& On OnLeave x=%d y=%d", pnt.x, pnt.y);
// if (!GetClientRect().Contains(event.GetPosition())) {
if (!rect.Contains(pnt)) {
if (m_bZoomEnabled) {
ZoomCard(zoom_out, 5, 5);
}
selected_ = false;
} else {
TRACELOG_WARNING("*****************************************************On OnLeave = false");
}
if (!selected_) {
// have_focus_ = false;
Refresh(false);
Update();
}
event.Skip();
}
void TypeCard::OnPaint(wxPaintEvent& event) {
wxPaintDC dc(this);
wxColour colour = selected_ ? CARD_SELECT_BACKGROUND_COLOUR : COMPONENT_UNSELECT_BACKGROUND_COLOUR;
wxCursor cur = selected_ ? wxCURSOR_HAND : wxCURSOR_ARROW;
dc.SetPen(wxPen(colour));
dc.SetBrush(wxBrush(colour));
this->SetCursor(cur);
const wxWindowList& list = this->GetChildren();
for (wxWindowList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext()) {
wxWindow* current = node->GetData();
if (current) {
current->SetBackgroundColour(colour);
current->SetCursor(cur);
}
}
dc.DrawRectangle(0, 0, this->GetSize().GetWidth(), GetSize().GetHeight());
}

Scrolling with mouse Win 8.1 Metro Hub Navigation

I am trying to find a solution to allow a Hub to pan with the mouse when its reaches the left or right boundary. I have implemented the code below which i have gleaned from various sources.
` private void theHubPointerMoved(object sender, PointerRoutedEventArgs e)
{ Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(null);
if (ptrPt.Position.X < this.ActualWidth - 20)
if (ptrPt.Position.X > 20)
{
//Do the SCROLLING HERE
var xcord = Math.Round(ptrPt.Position.X, 2);
var ycord = Math.Round(ptrPt.Position.Y, 2);
}
}
e.Handled = true;
}`
So it is relativley easy to see when the mouse is at the screen edge. I thought it would be easy to simply use the MyHub.ScrollViewer.ScrollToHorizontalOffset(xcord); but the Hub Scrollviewer doesnt expose this ScrollToHorizontalOffset function.
Can anyone assist?
Thanks.
Oh, it's exposed. If you can handle digging for it. Here's how:
http://xaml.codeplex.com/SourceControl/latest#Blog/201401-ScrollHub/MainPage.xaml.cs
In the example below, it is scrolling to a specific hub section. But you should be able to easily adapt it to your specific needs, I hope.
private void ScollHubToSection(Hub hub, HubSection section)
{
var visual = section.TransformToVisual(this.MyHub);
var point = visual.TransformPoint(new Point(0, 0));
var viewer = Helpers.FindChild<ScrollViewer>(hub, "ScrollViewer");
viewer.ChangeView(point.X, null, null);
}
Using this:
public class Helpers
{
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
T childType = child as T;
if (childType == null)
{
foundChild = FindChild<T>(child, childName);
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && frameworkElement.Name == childName)
{
foundChild = (T)child;
break;
}
}
else
{
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
Best of luck!

Qt TableView only sorting once

I have a QTableView that is populated with a QSqlQueryModel. I am trying to sort the table based on which RadioButton is checked, but nothing is happening when I press them. There was one point where I could get it to sort, but only once. What am I doing wrong here?
void MainWindow::on_openButton_clicked()
{
QString filePath = ui->lineEdit->text();
if( filePath != "" ){
if( openDB( filePath ) ){
ui->debugLabel->setText("Database opened");
MainWindow::populateTable();
}else{
ui->debugLabel->setText("Unable to open database");
}
} else {
ui->debugLabel->setText("Path is empty");
}
}
void MainWindow::populateTable(){
if( readDB() ){
ui->tableView->setModel(toast.dbModel);
}
}
void MainWindow::on_shootButton_toggled(bool checked)
{
if( checked ){
ui->tableView->sortByColumn( 0 );
}
}
void MainWindow::on_winButton_toggled(bool checked)
{
if( checked ){
ui->tableView->sortByColumn( 1 );
}
}
bool openDB(QString path){
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(path);
return db.open();
}
bool readDB(){
if( db.isOpen() ){
dbModel->setQuery( "select * from test", db );
return true;
} else {
return false;
}
}
QSqlQueryModel isn't sortable by default, QSqlTableModel is sortable but there's differences between the two. You can make QSqlQueryModel sortable by inheriting the class and reimplementing the sort() method though, if you have a look at the documentation for QAbstractItemModel it'll give you some details about it.

How to write a custom FindElement routine in Selenium?

I'm trying to figure out how to write a custom FindElement routine in Selenium 2.0 WebDriver. The idea would be something like this:
driver.FindElement(By.Method( (ISearchContext) => {
/* examine search context logic here... */ }));
The anonymous method would examine the ISearchContext and return True if it matches; False otherwise.
I'm digging through the Selenium code, and getting a bit lost. It looks like the actual By.* logic is carried out server-side, not client side. That seems to be complicating matters.
Any suggestions?
I do a multi-staged search. I have a method that performs a try catch and then a method that gets the element. In theory you could do a try catch until instead of this way but I like this way better because of my setup.
public bool CheckUntil(IWebDriver driver, string selectorType, string selectorInfo)
{
int Timer = 160;
bool itemFound = false;
for (int i = 0; i < Timer; i++)
if(itemFound)
{
i = 0
}
else
{
Thread.Sleep(500);
if(selectorType.ToLower() == "id" && TryCatch(driver, selectorType, selectorInfo))
{
if(driver.FindElement(By.Id(selectorInfo).Displayed)
{
itemFound = true;
}
}
else if(selectorType.ToLower() == "tagname" && TryCatch(driver, selectorType, selectorInfo))
{
if(driver.FindElement(By.TagName(selectorInfo).Displayed)
{
itemFound = true;
}
}
}
return itemFound;
}
Here's my try catch method you can add as many different types as you want id, cssselector, xpath, tagname, classname, etc.
public bool TryCatch(IWebDriver driver, string selectorType, string selectorInfo)
{
bool ElementFound = false;
try
{
switch(selectorType)
{
case "id":
driver.FindElement(By.Id(selectorInfo);
break;
case "tagname":
driver.FindElement(By.TagName(selectorInfo);
break;
}
ElementFound = truel
}
catch
{
ElementFound = false;
}
return ElementFound;
}
Ok, I figured out how to do this. I'm leveraging driver.ExecuteScript() to run custom js on the webdriver. It looks a bit like this:
function elementFound(elem) {
var nodeType = navigator.appName == ""Microsoft Internet
Explorer"" ? document.ELEMENT_NODE : Node.ELEMENT_NODE;
if(elem.nodeType == nodeType)
{
/* Element identification logic here */
}
else { return false; }
}
function traverseElement(elem) {
if (elementFound(elem) == true) {
return elem;
}
else {
for (var i = 0; i < elem.childNodes.length; i++) {
var ret = traverseElement(elem.childNodes[i]);
if(ret != null) { return ret; }
}
}
}
return traverseElement(document);