wxOwnerDrawnComboBox-inherited class is not focusable - wxwidgets

I have implemented an own combobox which is used as font-selector. To display what the selected fonts look like directly within the combobox, I created a new class FontStyleComboBox which inherits from wxOwnerDrawnComboBox. Following the full class is shown, only the font-management part is missing:
class FontStyleComboBox : public wxOwnerDrawnComboBox
{
private:
std::vector<wxFont> m_fontList;
public:
virtual void OnDrawItem(wxDC& dc,const wxRect& rect,int item,int flags) const
{
if (item == wxNOT_FOUND) return;
wxCoord w1,h1,w2,h2;
dc.GetTextExtent(GetString(item),&w1,&h1);
dc.DrawText(GetString(item),
rect.x + 3,
(rect.y + 0) + (rect.height / 2) - (dc.GetCharHeight() / 2)
);
dc.SetFont(m_fontList[item]);
dc.GetTextExtent(GetString(item),&w2,&h2);
if (w2<250)
{
if (rect.x+10+w1>135)
dc.DrawText(_T("AaBbCcDd 1234"),
rect.x+10+w1,
(rect.y + 0) + (rect.height / 2) - (dc.GetCharHeight() / 2)
);
else
dc.DrawText(_T("AaBbCcDd 1234"),
135,
(rect.y + 0) + (rect.height / 2) - (dc.GetCharHeight() / 2)
);
}
}
virtual void OnDrawBackground(wxDC& dc, const wxRect& rect,int item, int flags) const
{
// If item is selected or even, or we are painting the
// combo control itself, use the default rendering.
if ((flags & (wxODCB_PAINTING_CONTROL | wxODCB_PAINTING_SELECTED)) ||
(item & 1) == 0)
{
wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags);
return;
}
// Otherwise, draw every other background with different colour.
wxColour bgCol(245, 245, 255);
dc.SetBrush(wxBrush(bgCol));
dc.SetPen(wxPen(bgCol));
dc.DrawRectangle(rect);
}
virtual wxCoord OnMeasureItem(size_t item) const
{
return 20;
}
virtual wxCoord OnMeasureItemWidth(size_t item) const
{
return 400;
}
};
Unfortunately this font-combobox does not behave like a normal combobox:
when jumping through the elements within a GUI, as soon as the FontStyleComboBox should be focused, it is not highlighted
at the point when it should be focused, when pressing the up/down arrows, it does not slide through the elements of the combobox but changes the focus to the previous/next GUI element (right as somebody would hit shift-tab/tab)
So...any idea what could be missing here? Do I have to add some focus/focus-lost handling in this class?
This happens with wxWidgets 3.1 / Windows.

Solved: it was a problem of version 3.1 for Windows. With version 3.0/Linux it never occurred and since version 3.1.4 it is fixed for Windows too.

Related

qmk: Make a layer respond to two modifier keys being pressed?

In a qmk_firmware configuration, I can map a single modifier key to a new keymap layer using MO(x).
How can I do this such that two modifier keys must be pressed simultaneously?
Example: I would like to map [Fn][Ctrl]-[d] to generate a Unicode delta, [Fn][Ctrl]-[e] to generate a Unicode epsilon, etc.
You have to put your specific code into the custom Quantum function process_record_user:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// enter your code for [Fn][Ctrl]-[α] here
return true;
}
You can try the Quantum tab in the Firmware Builder. Even if it is end-of-life, you'll see, what is meant.
You can also set UNICODEMAP_ENABLE = yes and use the Unicode Map.
Something like this should do (half) the trick:
In function layer_state_set_user, check for layer Fn (some bit arithmetic similar to update_tri_layer_state) and the Ctrl state (get_mods() & MOD_MASK_CTRL). When in Fn layer and Ctrl is down, deactivate Ctrl (del_mods(MOD_MASK_CTRL)) and return state | x; otherwise return state & ~x.
Unfortunately, this will probably require Ctrl to be pressed before Fn.
At least that's what happens in my similar shift + layer _L4 => layer _S_L4 implementation in my keymap. It requires shift to be pressed before LT(_L4,…).
For the other direction (_L4 + shift => _S_L4), I have MO(_S_L4) on the shift keys in layer _L4, but that is somehow disabled by my layer_state_set_user.
What should "Fn + E" and "Fn + D" do (when Ctrl is not held)? For sake of example, I'll assume you want them to do PgUp and PgDn.
Here is how I would go about implementing this:
Enable Unicode input: In rules.mk, add UNICODEMAP_ENABLE = yes. In config.h, add #define UNICODE_SELECTED_MODES UC_WINC if you are on Windows. See the Unicode documentation for other OSs and options.
Define an "Fn" layer in the keymap.
Define a couple custom keycodes, and place them in the Fn layer at the d and e positions.
Handle the custom keys in process_record_user(), using get_mods() to test whether Ctrl is held. See also macros that respond to mods. Then use send_unicode_string() to type the Unicode symbol itself.
Code sketch:
// Copyright 2022 Google LLC.
// SPDX-License-Identifier: Apache-2.0
enum layers { BASE, FN, /* Other layers... */ };
enum custom_keycodes {
UPDIR = SAFE_RANGE,
FN_E,
FN_D,
// Other custom keys...
};
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
[BASE] = LAYOUT(...),
[FN] = LAYOUT(..., FN_E, ..., FN_D, ...),
...
};
const uint32_t unicode_map[] PROGMEM = {};
static void symbol_key(uint16_t* registered_key,
keyrecord_t* record,
uint16_t default_keycode,
const char* symbol,
const char* uppercase_symbol) {
if (record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
if (ctrl_held) { // Is the Ctrl mod held?
unregister_mods(MOD_MASK_CTRL); // Clear the Ctrl mod.
// Type Unicode symbol according to whether shift is active.
send_unicode_string(shifted ? uppercase_symbol : symbol);
*registered_key = KC_NO;
} else {
*registered_key = default_keycode;
register_code16(*registered_key);
}
} else { // On key release.
unregister_code16(*registered_key);
*registered_key = KC_NO;
}
}
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
switch (keycode) {
case FN_E: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGUP, "ε", "Ε");
} return false;
case FN_D: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGDN, "δ", "Δ");
} return false;
}
return true;
}

Bukkit countdown timer starts counting down infinite (2,1,-1,-2 etc)

So i got this problem when one - two+ players are online the countdown timer goes in minus like this 4,3,2,1,0 -1,-2,-3 etc.
Does anyone know how i can fix this, been struggling with it for quite a long time now :P
Here is my countdown class:
#Override
public void run() {
if (timeUntilStart == 0) {
if (!Game.canStart()) {
if(Bukkit.getOnlinePlayers().size() <= 2) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
for (Player p : Bukkit.getOnlinePlayers()) p.playSound(p.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}else{
if(Game.canStart()) {
if(Bukkit.getOnlinePlayers().size() >= 2) {
Game.start();
}
}
}
}
}
boolean broadcast = false;
for (Player p : Bukkit.getOnlinePlayers()) {
p.setLevel(timeUntilStart);
if (timeUntilStart < 11 || timeUntilStart == 120 ||timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if (timeUntilStart == 1) p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
broadcast = true;
}
}
if (broadcast) ChatUtilities.broadcast(String.valueOf(timeUntilStart) + " §6Seconds until the game starts!");{
}
{
timeUntilStart -= 1;
}
}
}
The only case in which your method returns and timeUtilStart is not decremented is
timeUntilStart == 0 && !Game.canStart() && Bukkit.getOnlinePlayers().size() <= 2
As defined by the first three if blocks in your code.
This explains why your countdown does not stop when you have 3 or more players around.
I believe this mistake happened because of messy {} blocks and indentation. Take a step back and closely read the code you wrote again and fix brackets as well as indentation.
Good formatting is not a pointless chore, it's an essential tool to help yourself understand what you already wrote.
Have you tried using the bukkit scheduler? People tend to forget that bukkit's API can handle countdowns very well. Just call the scheduler with this
myInteger = Bukkit's.getScheduler.scheduleSyncRepeatingTask(plugin, new runnable(), 0L, 20L)
Put your JavaPlugin extension class in as plugin, use runnable adding unimplemented methods, 0L is ticks before first run, 20L is ticks between each run.
Cancel the countdown like this
Bukkit's.getScheduler.cancelTask(myInteger)

Kinect background removal

I followed the code provided by Robert Levy at this link: http://channel9.msdn.com/coding4fun/kinect/Display-Kinect-color-image-containing-only-players-aka-background-removal
I tried implementing it into my existing code, and have had inconsistent results. If the user is in the kinect's field of view when the program starts up it will remove the background some of the time. If the user walks into the field of view it will not pick them up.
namespace KinectUserRecognition
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//Kinect Runtime
Runtime kinect = Runtime.Kinects[0];
PlanarImage colorImage;
PlanarImage depthImage;
bool isDepthImage;
WriteableBitmap player1;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
isDepthImage = false;
//UseDepthAndPlayerIndex and UseSkeletalTracking
kinect.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseColor);// | RuntimeOptions.UseSkeletalTracking);
//register for event
kinect.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_VideoFrameReady);
kinect.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
//Video image type
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480,
ImageType.Color);
//DepthAndPlayerIndex ImageType
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240,
ImageType.DepthAndPlayerIndex);
}
void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
{
colorImage = e.ImageFrame.Image;
image1.Source = BitmapSource.Create(colorImage.Width, colorImage.Height, 96, 96,
PixelFormats.Bgr32, null, colorImage.Bits, colorImage.Width * colorImage.BytesPerPixel);
if (isDepthImage)
{
player1 = GeneratePlayerImage(e.ImageFrame, 1);
image3.Source = player1;
}
}
void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
{
//Convert depth information for a pixel into color information
byte[] ColoredBytes = GenerateColoredBytes(e.ImageFrame);
depthImage = e.ImageFrame.Image;
image2.Source = BitmapSource.Create(depthImage.Width, depthImage.Height, 96, 96, PixelFormats.Bgr32, null,
ColoredBytes, depthImage.Width * PixelFormats.Bgr32.BitsPerPixel / 8);
isDepthImage = true;
}
private WriteableBitmap GeneratePlayerImage(ImageFrame imageFrame, int playerIndex)
{
int depthWidth = kinect.DepthStream.Width;
int depthHeight = kinect.DepthStream.Height;
WriteableBitmap target = new WriteableBitmap(depthWidth, depthHeight, 96, 96, PixelFormats.Bgra32, null);
var depthRect = new System.Windows.Int32Rect(0, 0, depthWidth, depthHeight);
byte[] color = imageFrame.Image.Bits;
byte[] output = new byte[depthWidth * depthHeight * 4];
//loop over each pixel in the depth image
int outputIndex = 0;
for (int depthY = 0, depthIndex = 0; depthY < depthHeight; depthY++)
{
for(int depthX = 0; depthX < depthWidth; depthX++, depthIndex +=2)
{
short depthValue = (short)(depthImage.Bits[depthIndex] | (depthImage.Bits[depthIndex + 1] << 8));
int colorX, colorY;
kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(
imageFrame.Resolution,
imageFrame.ViewArea,
depthX, depthY, //depth coordinate
depthValue, //depth value
out colorX, out colorY); //color coordinate
//ensure that the calculate color location is within the bounds of the image
colorX = Math.Max(0, Math.Min(colorX, imageFrame.Image.Width - 1));
colorY = Math.Max(0, Math.Min(colorY, imageFrame.Image.Height - 1));
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 0];
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 1];
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 2];
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0;
}
}
target.WritePixels(depthRect, output, depthWidth * PixelFormats.Bgra32.BitsPerPixel / 8, 0);
return target;
//return output;
}
private static int GetPlayerIndex(byte firstFrame)
{
//returns 0 = no player, 1 = 1st player, 2 = 2nd player...
//bitwise & on firstFrame
return (int)firstFrame & 7;
}
}
}
-Edit 1-
I think I've narrowed the problem down, but I'm not sure of a way to resolve it. I assumed that having only one person in the kinect's field of view would return a value of one from my "GetPlayerIndex" method. This is not the case. I was hoping to produce a separate image for each person with the background removed. What type of values should I assume to receive from:
-Edit 2-
From my tests I've noticed that I can a max value of 6 for the player index, but the index that I get isn't consistent. If there a way to know what player index will be assigned to a skeleton? For example, if I were the only person in the fov would there be a way to know that my player index would always be 1?
The player index is not guaranteed to be anything. Once it catches a skeleton, the index will stay the same for that skeleton until it loses sight of it, but you can't assume that the first player will be 1, the second 2, etc.
What you'll need to do is determine a valid skeleton index prior to the player1 = GeneratePlayerImage(e.ImageFrame, 1); call, or alter the GeneratePlayerImage function to find an index. If you're only interested in removing the background and leaving the pixels for all the people in the frame untouched, just change this:
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0;
to this, which will just check for ANY player, instead of a specific player:
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) != 0 ? (byte)255 : (byte)0;
The other two ways I can think of to do this for a specific player instead of all players:
Open the Kinect's Skeleton feed, and loop through the array of skeletons it gives you to find a valid index. Create a global integer to hold this index, then call the GeneratePlayerImage method with this global integer.
Change the GeneratePlayerImage method to check for a player index in each pixel, and if one is found use that index to remove the background for the entire image (ignore any other index it finds).

Dynamic grid using FlashDevelop & Actionscript 2.0

I'm new to actionscript. What I'm tryin to do is simulate traffic flow near a 2 lane intersection, following Wolfram's rule 184. To begin with, I'm trying to create a grid (8x8 of which the intersection is between the middle two rows and the middle two columns, like a plus sign) whose cells have the following attributes:
color = white;
car = false;
when clicked:
color = red;
car = true (a car is present);
So, after the user clicks cells to position the cars initially and presses the start button, the simulation will begin.
Here's my code so far (apologies for incorrect formatting):
class Main
{
private var parent:MovieClip;
public static function main(mc:MovieClip)
{
var app = new Main(mc);
}
public function Main(mc:MovieClip)
{
this.parent = mc;
//grid settings
var Cell:MovieClip = mc.createEmptyMovieClip("cell", mc.getNextHighestDepth());
var x:Number = 0;
var y:Number = 0;
var color:Number = 0xffffff;
var car:Boolean = false;
for (y = 0; y < 3 * Stage.height / 8; y += Stage.height / 8)
{
for (x = 3*Stage.width/8; x < 5*Stage.width/8; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8) - 5, (Stage.height / 8) - 5, color, 100);
}
}
for (y = 3*Stage.height/8; y < 5 * Stage.height / 8; y += Stage.height / 8)
{
for (x = 0; x < Stage.width; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8)-5, (Stage.height / 8)-5, color, 100);
}
}
for (y = 5*Stage.height/8; y < Stage.height; y += Stage.height / 8)
{
for (x = 3*Stage.width/8; x < 5*Stage.width/8; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8)-5, (Stage.height / 8)-5, color, 100);
}
}
Cell.onMouseDown()
{
Cell.color = UI.RED;
Cell.car = true;
}
}
}
I know there's quite a few things gone wrong here. First of all, the cell color doesn't change on mouse down. Do i need to make movie clip for each cell in the for loops? I think it would be easier to make a grid of objects with given attributes, but i don't know how to do that. Would really appreciate if someone helps me out.
From what I can tell, issue with your current approach is that using drawRect() literally draws pixels on to the stage, which means you'll have no reference to those shapes in future frames. right now, you've got one MovieClip that has been drawn many times. What you need is a lot of MovieClips so you have a reference to each cell that you can update/edit every frame.
Your best bet is to do the following (I'll just provide pseudo because I'm a bit shaky on AS2 syntax):
A) Create an array to hold all of the Cells. Call it:
var Cells:Array = new Array();
B) During each step of the loops in your constructor, do 4 things.
1) Create a new MovieClip `var tempCell:MovieClip = new MovieClip();
2) Draw a rectangle on to each MovieClip: A tutorial for the graphics API in AS2 http://www.actionscript.org/resources/articles/727/1/Drawing-shapes-with-AS2/Page1.html
3) Add an event listenerto each MovieClip that points to a common event handler. This listener listens for mouse clicks on that MovieClip (or MOUSE_DOWN)
4) and use Cells.push(tempClip) to add that new MovieClip to your array so you now have one object that contains a reference to all of your cells.
C) Create an click event handler that redraws the cell that has been clicked. Try MouseEvent.target
You have another option to using the graphics API to draw rectangles, and that is to simply add and remove stock graphics from your Flash library. You'll have to draw these graphics in Flash and then 'Export for Actionscript' to call them up.
Hope this points you in the right direction!
J

SWT Canvas Location

I'm using the most recent stable version of SWT.
I have a Shell containing a ToolBar, a ScrolledComposite, and a Canvas. The Canvas is set as the ScrolledComposite's content (e.g. scrolledComposite.setContent(canvas)). The Canvas is created with a specific size that never changes (say, 400 x 400). Whereas the ScrolledComposite is constantly growing or shrinking to fill the available parent shell's client area.
I have a resize listener attached to the parent Shell that attempts to do the following: a) grow the ScrolledComposite as described above and b) center the Canvas both horizontally and vertically within the ScrolledComposite (see below for example code).
This works exactly as it should on Mac OS X, however on Windows the resize event is fired and the new locations are properly calculated but ultimately the Canvas snaps back to 0,0. One other small piece of information is that if you continuously resize the window, you can see the canvas flickering and it looks as if it's being briefly drawn at the correct location.
_shell.addListener (SWT.Resize, new Listener () {
public void handleEvent (Event e)
{
int toolBarOffset = _toolBar.getSize().y;
Rectangle clientArea = _shell.getClientArea();
_scrollComposite.setBounds(0, toolBarOffset, clientArea.width, clientArea.height - toolBarOffset);
Point canvasSize = _canvas.getSize();
int canvasX = Math.max(0, (clientArea.width / 2) - (canvasSize.x / 2));
int canvasY = Math.max(0, ((clientArea.height - toolBarOffset) / 2) - (canvasSize.y / 2));
_canvas.setLocation(canvasX, canvasY);
}
});
Not sure if you've already figured it out, but the problem is that the ScrolledComposite always sets the content to 0/0 when it is resized. I'm not sure why your approach works on OS X, and I've not tested my example as I don't have a Mac here.
The solution is to use a filler composite that is always at least as big as the client area from the ScrolledComposite. In that filler, you can then center the Canvas correctly.
I've made a small example, as an added bonus it also centers the canvas if the client area of the SC is smaller than the canvas ( because I've first thought that was your question :) )
You may have to make some minor adjustments, I guess there are some glitches on OS X with that code...
package test;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class Test {
public static void main(final String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout( new FillLayout() );
final ScrolledComposite sComp = new ScrolledComposite( shell, SWT.H_SCROLL | SWT.V_SCROLL );
final Composite fillComp = new Composite( sComp, SWT.NONE );
sComp.setLayout( new FillLayout() );
final Canvas c = new Canvas( fillComp, SWT.DOUBLE_BUFFERED );
c.addPaintListener( new PaintListener() {
public void paintControl(PaintEvent e) {
Point p = c.getSize();
e.gc.setBackground( display.getSystemColor( SWT.COLOR_RED ));
e.gc.fillRectangle( 0, 0, p.x, p.y );
e.gc.setBackground( display.getSystemColor( SWT.COLOR_BLUE ));
e.gc.fillRectangle( p.x / 2 - 10, p.y / 2 - 10, 20, 20 );
}
});
c.setSize( 400, 400 );
sComp.setContent( fillComp );
sComp.addControlListener( new ControlAdapter() {
#Override
public void controlResized(ControlEvent e) {
Rectangle clientArea = sComp.getClientArea();
Point cSize = c.getSize();
int fillX = Math.max( clientArea.width, cSize.x );
int fillY = Math.max( clientArea.height, cSize.y );
fillComp.setSize( fillX, fillY );
int cX = ( clientArea.width - cSize.x ) / 2;
int cY = ( clientArea.height - cSize.y ) / 2;
sComp.setOrigin( -cX, -cY );
int locX = Math.max( cX, 0 );
int locY = Math.max( cY, 0 );
c.setLocation( locX, locY );
}
});
shell.open();
shell.pack();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}