Constant Width SashForm - java

My application has a SashForm with two children. I want the left child to stay the same size when the window is resized. I want the same thing Eclipse does with the Package Explorer and the main editor. When you resize the window only the text editor changes size. However, the Package Explorer is still resizeable by the sash.
I tried using the following
sashForm.addControlListener(new ControlAdapter() {
#Override
public void controlResized(ControlEvent e) {
int width = sashForm.getClientArea().width;
int[] weights = sashForm.getWeights();
weights[1] = width - weights[0];
sashForm.setWeights(weights);
}
});
The problem is the width of the left size either shrinks to 0 or expands too much. It looks like the weights are updated before this is called or something.
If I set weights[0] equal to some constant it does what I want.

I managed to get an example running that should give you an idea how to solve your problem. The thing is, that the SashForm uses weights rather than pixels. So you have to compute the percentage the left child has to occupy based on the parent size and assign the rest to the right child.
In my code example, you can specify the width of the left child and set a minimal size for the right child, such that the SashForm will always show both.
private static final int MIN_WIDTH_LEFT = 100;
private static final int MIN_WIDTH_RIGHT = 50;
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
Button button = new Button(form, SWT.PUSH);
button.setText("Left");
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setWeights(new int[] {1, 2});
shell.addListener(SWT.Resize, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
int width = shell.getClientArea().width;
int[] weights = form.getWeights();
if(width >= MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT)
{
weights[0] = 1000000 * MIN_WIDTH_LEFT / width;
weights[1] = 1000000 - weights[0];
}
else
{
weights[0] = 1000000 * MIN_WIDTH_LEFT / (MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT);
weights[1] = 1000000 * MIN_WIDTH_RIGHT / (MIN_WIDTH_LEFT + MIN_WIDTH_RIGHT);
}
System.out.println(width + " " + Arrays.toString(weights));
form.setWeights(weights);
}
});
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
This is what it looks like:
Startup:
After resizing:
When decreasing the window size until it is too small to show both minimal sizes:
As you can see in this case, the minimal size for the left child is ignored to still be able to show both childs.

This is the best solution I could come up with.
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
public class Main {
private static int leftWidth, oldWeight;
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
shell.setSize(600, 400);
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
final Button button = new Button(form, SWT.PUSH);
button.setText("Left");
button.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event arg0) {
int[] weights = form.getWeights();
// oldWeights is used to distinguish between a window resize and
// a sash move
if (oldWeight != weights[0]) {
System.out.println("Weights changed!");
oldWeight = weights[0];
leftWidth = (int) Math.round((double) form.getClientArea().width
* (double) weights[0]
/ (double) (weights[0] + weights[1]));
}
}
});
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setWeights(new int[] { 200, 800 });
leftWidth = 200;
form.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event arg0) {
int width = form.getClientArea().width;
int[] weights = form.getWeights();
double perChange = (double) leftWidth / (double) width;
weights[0] = (int) (perChange * 1000.0);
weights[1] = 1000 - weights[0];
// oldWeights must be set before form.setWeights
oldWeight = weights[0];
form.setWeights(weights);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
The sash jumps around about 1px when the window is resized due to rounding issues, but it seems to do what I want.
This is a very hacky solution and I would like to know if there is a better one. It also crashes if you make the window smaller than the left button, but that is easy to fix.

Have to rewrite SashForm to get this behavior. new SashForm(Composite parent, int style) is old behavior; new SashForm(Composite parent, int style, false) uses widths/heights specified in pixels.
Not tested with more than two Composite children of the SashForm, and odd behavior if you don't setLength when using new behavior, but will not break existing uses of SashForm
e.g.:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
Button button = new Button(form, SWT.PUSH);
button.setText("Left");
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setLengths(new int[] { 250, 25 });
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
First button will default to 250 pixels, second the remainder shell
SashForm.java:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class SashForm extends Composite {
/**
* The width of all sashes in the form.
*/
public int SASH_WIDTH = 3;
int sashStyle;
final private boolean weighted;
Sash[] sashes = new Sash[0];
// Remember background and foreground
// colors to determine whether to set
// sashes to the default color (null) or
// a specific color
Color background = null;
Color foreground = null;
Control[] controls = new Control[0];
Control maxControl = null;
Listener sashListener;
static final int DRAG_MINIMUM = 20;
public SashForm(Composite parent, int style) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
weighted = true;
}
public SashForm(Composite parent, int style, boolean weighted) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
this.weighted = weighted;
}
static int checkStyle (int style) {
int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
Sash createSash() {
Sash sash = new Sash(this, sashStyle);
sash.setBackground(background);
sash.setForeground(foreground);
sash.setToolTipText(getToolTipText());
sash.addListener(SWT.Selection, sashListener);
return sash;
}
#Override
public int getOrientation() {
//checkWidget();
return (sashStyle & SWT.VERTICAL) != 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
}
/**
* Returns the width of the sashes when the controls in the SashForm are
* laid out.
*
* #return the width of the sashes
*
* #exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* #since 3.4
*/
public int getSashWidth() {
checkWidget();
return SASH_WIDTH;
}
#Override
public int getStyle() {
int style = super.getStyle();
style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
if ((sashStyle & SWT.SMOOTH) != 0) style |= SWT.SMOOTH;
return style;
}
/**
* Answer the control that currently is maximized in the SashForm.
* This value may be null.
*
* #return the control that currently is maximized or null
*/
public Control getMaximizedControl(){
//checkWidget();
return this.maxControl;
}
public int[] getWeights() {
checkWidget();
Control[] cArray = getControls(false);
int[] ratios = new int[cArray.length];
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = (int)(((SashFormData)data).weight * 1000 >> 16);
} else {
ratios[i] = 200;
}
}
return ratios;
}
Control[] getControls(boolean onlyVisible) {
Control[] children = getChildren();
Control[] result = new Control[0];
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Sash) continue;
if (onlyVisible && !children[i].getVisible()) continue;
Control[] newResult = new Control[result.length + 1];
System.arraycopy(result, 0, newResult, 0, result.length);
newResult[result.length] = children[i];
result = newResult;
}
return result;
}
boolean getWeighted() {
return weighted;
}
void onDragSash(Event event) {
Sash sash = (Sash)event.widget;
int sashIndex = -1;
for (int i= 0; i < sashes.length; i++) {
if (sashes[i] == sash) {
sashIndex = i;
break;
}
}
if (sashIndex == -1) return;
Control c1 = controls[sashIndex];
Control c2 = controls[sashIndex + 1];
Rectangle b1 = c1.getBounds();
Rectangle b2 = c2.getBounds();
Rectangle sashBounds = sash.getBounds();
Rectangle area = getClientArea();
boolean correction = false;
if (getOrientation() == SWT.HORIZONTAL) {
correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
int totalWidth = b2.x + b2.width - b1.x;
int shift = event.x - sashBounds.x;
b1.width += shift;
b2.x += shift;
b2.width -= shift;
if (b1.width < DRAG_MINIMUM) {
b1.width = DRAG_MINIMUM;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = totalWidth - b2.x;
event.x = b1.x + b1.width;
event.doit = false;
}
if (b2.width < DRAG_MINIMUM) {
b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = DRAG_MINIMUM;
event.x = b1.x + b1.width;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.width << 16) + area.width - 1) / area.width;
((SashFormData)data1).length = b1.width;
((SashFormData)data2).weight = (((long)b2.width << 16) + area.width - 1) / area.width;
((SashFormData)data2).length = b2.width;
} else {
correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
int totalHeight = b2.y + b2.height - b1.y;
int shift = event.y - sashBounds.y;
b1.height += shift;
b2.y += shift;
b2.height -= shift;
if (b1.height < DRAG_MINIMUM) {
b1.height = DRAG_MINIMUM;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = totalHeight - b2.y;
event.y = b1.y + b1.height;
event.doit = false;
}
if (b2.height < DRAG_MINIMUM) {
b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = DRAG_MINIMUM;
event.y = b1.y + b1.height;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.height << 16) + area.height - 1) / area.height;
((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
}
if (correction || (event.doit && event.detail != SWT.DRAG)) {
c1.setBounds(b1);
sash.setBounds(event.x, event.y, event.width, event.height);
c2.setBounds(b2);
}
}
#Override
public void setOrientation(int orientation) {
checkWidget();
if (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT) {
super.setOrientation(orientation);
return;
}
if (getOrientation() == orientation) return;
if (orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
for (int i = 0; i < sashes.length; i++) {
sashes[i].dispose();
sashes[i] = createSash();
}
layout(false);
}
#Override
public void setBackground (Color color) {
super.setBackground(color);
background = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setBackground(background);
}
}
#Override
public void setForeground (Color color) {
super.setForeground(color);
foreground = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setForeground(foreground);
}
}
#Override
public void setLayout (Layout layout) {
checkWidget();
return;
}
public void setMaximizedControl(Control control){
checkWidget();
if (control == null) {
if (maxControl != null) {
this.maxControl = null;
layout(false);
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(true);
}
}
return;
}
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(false);
}
maxControl = control;
layout(false);
}
public void setSashWidth(int width) {
checkWidget();
if (SASH_WIDTH == width) return;
SASH_WIDTH = width;
layout(false);
}
#Override
public void setToolTipText(String string) {
super.setToolTipText(string);
for (int i = 0; i < sashes.length; i++) {
sashes[i].setToolTipText(string);
}
}
public void setWeights(int[] weights) {
checkWidget();
Control[] cArray = getControls(false);
if (weights == null || weights.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < weights.length; i++) {
if (weights[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += weights[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).weight = (((long)weights[i] << 16) + total - 1) / total;
}
layout(false);
}
public void setLengths(int[] lengths) {
checkWidget();
Control[] cArray = getControls(false);
if (lengths == null || lengths.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < lengths.length; i++) {
if (lengths[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += lengths[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).length = lengths[i];
}
layout(false);
}
}
SashFormData.java:
class SashFormData {
long weight;
int length;
String getName () {
String string = getClass ().getName ();
int index = string.lastIndexOf ('.');
if (index == -1) return string;
return string.substring (index + 1, string.length ());
}
#Override
public String toString () {
return getName()+" {length="+length+", weight="+weight+"}"; //$NON-NLS-2$
}
}
SashFormLayout.java:
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
class SashFormLayout extends Layout {
#Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
SashForm sashForm = (SashForm)composite;
Control[] cArray = sashForm.getControls(true);
int width = 0;
int height = 0;
if (cArray.length == 0) {
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
// determine control sizes
boolean vertical = sashForm.getOrientation() == SWT.VERTICAL;
if (sashForm.getWeighted()) {
int maxIndex = 0;
int maxValue = 0;
for (int i = 0; i < cArray.length; i++) {
if (vertical) {
Point size = cArray[i].computeSize(wHint, SWT.DEFAULT, flushCache);
if (size.y > maxValue) {
maxIndex = i;
maxValue = size.y;
}
width = Math.max(width, size.x);
} else {
Point size = cArray[i].computeSize(SWT.DEFAULT, hHint, flushCache);
if (size.x > maxValue) {
maxIndex = i;
maxValue = size.x;
}
height = Math.max(height, size.y);
}
}
// get the ratios
long[] ratios = new long[cArray.length];
long total = 0;
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = ((SashFormData)data).weight;
} else {
data = new SashFormData();
cArray[i].setLayoutData(data);
((SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
}
total += ratios[i];
}
if (ratios[maxIndex] > 0) {
int sashwidth = sashForm.sashes.length > 0 ? sashForm.SASH_WIDTH + sashForm.sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (vertical) {
height += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
} else {
width += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
}
}
} else {
int maxIndex = 0;
int maxValue = 0;
for (int i = 0; i < cArray.length; i++) {
if (vertical) {
Point size = cArray[i].computeSize(wHint, SWT.DEFAULT, flushCache);
if (size.y > maxValue) {
maxIndex = i;
maxValue = size.y;
}
width = Math.max(width, size.x);
} else {
Point size = cArray[i].computeSize(SWT.DEFAULT, hHint, flushCache);
if (size.x > maxValue) {
maxIndex = i;
maxValue = size.x;
}
height = Math.max(height, size.y);
}
}
// get the lengths
int[] lengths = new int[cArray.length];
long total = 0;
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
lengths[i] = ((SashFormData)data).length;
} else {
data = new SashFormData();
cArray[i].setLayoutData(data);
((SashFormData)data).length = sashForm.getOrientation() == SWT.HORIZONTAL ? cArray[i].getSize().x : cArray[i].getSize().y;
}
total += lengths[i];
}
if (lengths[maxIndex] > 0) {
int sashwidth = sashForm.sashes.length > 0 ? sashForm.SASH_WIDTH + sashForm.sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (vertical) {
height += total + (cArray.length - 1) * sashwidth;
} else {
width += total + (cArray.length - 1) * sashwidth;
}
}
}
width += sashForm.getBorderWidth()*2;
height += sashForm.getBorderWidth()*2;
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
#Override
protected boolean flushCache(Control control) {
return true;
}
#Override
protected void layout(Composite composite, boolean flushCache) {
SashForm sashForm = (SashForm)composite;
Rectangle area = sashForm.getClientArea();
if (area.width <= 1 || area.height <= 1) return;
Control[] newControls = sashForm.getControls(true);
if (sashForm.controls.length == 0 && newControls.length == 0) return;
sashForm.controls = newControls;
Control[] controls = sashForm.controls;
if (sashForm.maxControl != null && !sashForm.maxControl.isDisposed()) {
for (int i= 0; i < controls.length; i++){
if (controls[i] != sashForm.maxControl) {
controls[i].setBounds(-200, -200, 0, 0);
} else {
controls[i].setBounds(area);
}
}
return;
}
// keep just the right number of sashes
if (sashForm.sashes.length < controls.length - 1) {
Sash[] newSashes = new Sash[controls.length - 1];
System.arraycopy(sashForm.sashes, 0, newSashes, 0, sashForm.sashes.length);
for (int i = sashForm.sashes.length; i < newSashes.length; i++) {
newSashes[i] = sashForm.createSash();
}
sashForm.sashes = newSashes;
}
if (sashForm.sashes.length > controls.length - 1) {
if (controls.length == 0) {
for (int i = 0; i < sashForm.sashes.length; i++) {
sashForm.sashes[i].dispose();
}
sashForm.sashes = new Sash[0];
} else {
Sash[] newSashes = new Sash[controls.length - 1];
System.arraycopy(sashForm.sashes, 0, newSashes, 0, newSashes.length);
for (int i = controls.length - 1; i < sashForm.sashes.length; i++) {
sashForm.sashes[i].dispose();
}
sashForm.sashes = newSashes;
}
}
if (controls.length == 0) return;
Sash[] sashes = sashForm.sashes;
if (sashForm.getWeighted()) {
// get the ratios
long[] ratios = new long[controls.length];
long total = 0;
for (int i = 0; i < controls.length; i++) {
Object data = controls[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = ((SashFormData)data).weight;
} else {
data = new SashFormData();
controls[i].setLayoutData(data);
((SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
}
total += ratios[i];
}
int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (sashForm.getOrientation() == SWT.HORIZONTAL) {
int width = (int)(ratios[0] * (area.width - sashes.length * sashwidth) / total);
int x = area.x;
controls[0].setBounds(x, area.y, width, area.height);
x += width;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = (int)(ratios[i] * (area.width - sashes.length * sashwidth) / total);
controls[i].setBounds(x, area.y, width, area.height);
x += width;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = area.width - x;
controls[controls.length - 1].setBounds(x, area.y, width, area.height);
}
} else {
int height = (int)(ratios[0] * (area.height - sashes.length * sashwidth) / total);
int y = area.y;
controls[0].setBounds(area.x, y, area.width, height);
y += height;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = (int)(ratios[i] * (area.height - sashes.length * sashwidth) / total);
controls[i].setBounds(area.x, y, area.width, height);
y += height;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = area.height - y;
controls[controls.length - 1].setBounds(area.x, y, area.width, height);
}
}
} else {
// get the lengths
int[] lengths = new int[controls.length];
for (int i = 0; i < controls.length; i++) {
Object data = controls[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
lengths[i] = ((SashFormData)data).length;
} else {
data = new SashFormData();
controls[i].setLayoutData(data);
((SashFormData)data).length = sashForm.getOrientation() == SWT.HORIZONTAL ? controls[i].getSize().x : controls[i].getSize().y;
}
}
int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (sashForm.getOrientation() == SWT.HORIZONTAL) {
int width = lengths[0];
int x = area.x;
controls[0].setBounds(x, area.y, width, area.height);
x += width;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = lengths[i];
controls[i].setBounds(x, area.y, width, area.height);
x += width;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = area.width - x;
controls[controls.length - 1].setBounds(x, area.y, width, area.height);
}
} else {
int height = lengths[0];
int y = area.y;
controls[0].setBounds(area.x, y, area.width, height);
y += height;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = lengths[i];
controls[i].setBounds(area.x, y, area.width, height);
y += height;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = area.height - y;
controls[controls.length - 1].setBounds(area.x, y, area.width, height);
}
}
}
}
}

Related

Depth system - previous 'top' item flashes upon change

I'm trying to set up a depth system of sorts in processing.
The goal is for it to function similar to a (Windows) window.
I have a class called 'Window' and that can take some arguments and it will successfully draw a window that can be dragged around.
The depth system works as it stands right now. I can't click on windows 'under' the current window and if I click on another window, the order of the windows is switched correctly.
The problem is that whenever I switch between windows, the previously selected window flashes (is not drawn) for a frame, and then appears again.
I cannot work out why this happens at all. Here's my code, let me know if you need any further info.
Windows.pde:
Window[] wins;
int win_count = 0;
boolean win_drag = false;
int win_selected = 2;
void setup()
{
size(800, 600);
wins = new Window[3];
wins[0] = new Window("Test", 20, 20, 300, 200);
wins[1] = new Window("Test 2", 20, 260, 350, 225);
wins[2] = new Window("Test 3", 400, 20, 250, 150);
}
void draw()
{
background(10);
for (int i = 0; i < wins.length; i ++)
{
wins[i].draw_window();
}
}
void bringToTop(Window winID)
{
Window[] new_wins;
new_wins = new Window[wins.length];
int win_pos = -1;
for (int i = 0; i < wins.length; i ++)
{
if (wins[i] == winID)
{
win_pos = i;
break;
}
}
arrayCopy(wins, 0, new_wins, 0, win_pos);
arrayCopy(wins, win_pos + 1, new_wins, win_pos, wins.length - win_pos - 1);
new_wins[wins.length - 1] = winID;
arrayCopy(new_wins, wins);
}
boolean isOnTop(Window winID)
{
int win_pos = -1;
for (int i = 0; i < wins.length; i ++)
{
if (wins[i] == winID)
{
win_pos = i;
break;
}
}
Window[] top_wins;
top_wins = new Window[wins.length];
int winTopCount = 0;
for (int i = 0; i < wins.length; i ++)
{
if (mouse_in_rect(wins[i].winX, wins[i].winY, wins[i].winW, wins[i].winH + 24))
{
top_wins[winTopCount] = wins[i];
winTopCount ++;
}
}
int last_real_win = -1;
for (int i = 0; i < top_wins.length; i ++)
{
if (top_wins[i] != null)
{
last_real_win = i;
}
}
return (wins[win_pos] == top_wins[last_real_win]);
}
WindowObj.pde:
class Window
{
String winT;
int winX;
int winY;
int winW;
int winH;
boolean dragging;
int winXOff;
int winYOff;
int winTH;
int my_id;
Window(String ttl, int WX, int WY, int WW, int WH)
{
winT = ttl;
winX = WX;
winY = WY;
winW = WW;
winH = WH;
dragging = false;
winXOff = 0;
winYOff = 0;
winTH = 24;
my_id = win_count ++;
}
void draw_window()
{
if (win_selected == my_id)
{
fill(60);
}
else
{
fill(40);
}
rect(winX, winY, winW, winTH);
fill(25);
rect(winX, winY + 24, winW, winH);
if (dragging == true)
{
winX = mouseX + winXOff;
winY = mouseY + winYOff;
if (winX < 0)
{
winX = 0;
}
if (winX > width - winW - 1)
{
winX = width - winW - 1;
}
if (winY < 0)
{
winY = 0;
}
if (winY > height - winH - winTH - 1)
{
winY = height - winH - winTH - 1;
}
}
Window win_pos = wins[0];
for (int i = 0; i < wins.length; i ++)
{
if (wins[i].my_id == my_id)
{
win_pos = wins[i];
}
}
if (mouse_in_rect(winX, winY, winW, 24) && mousePressed && mouseButton == LEFT && dragging == false && isOnTop(win_pos) && win_drag == false)
{
dragging = true;
winXOff = winX - mouseX;
winYOff = winY - mouseY;
win_drag = true;
win_selected = my_id;
bringToTop(win_pos);
}
if (mouse_in_rect(winX, winY + 24, winW, winH) && mousePressed && mouseButton == LEFT && dragging == false && isOnTop(win_pos) && win_drag == false)
{
win_selected = my_id;
bringToTop(win_pos);
}
if (dragging == true)
{
if (mouseButton != LEFT)
{
win_drag = false;
dragging = false;
winXOff = 0;
winYOff = 0;
}
}
}
}
mouseFunctions.pde:
boolean mouse_in_rect(int mX, int mY, int mW, int mH)
{
int but_x = mX;
int but_y = mY;
int but_w = mW;
int but_h = mH;
if (mouseX > but_x && mouseY > but_y && mouseX < but_x + but_w && mouseY < but_y + but_h)
{
return true;
}
else
{
return false;
}
}
The issue is caused, because you do the calculation of the window order and the drawing in a single loop.
If the position of a window has changed, the drawing of a window may be omitted, while the drawing of an other window is done twice. Note, the index of the windows in the array wins changed.
Split the drawing and the update of the windows to 2 separate methods:
class Window
{
// ...
void draw_window()
{
if (win_selected == my_id)
{
fill(60);
}
else
{
fill(40);
}
rect(winX, winY, winW, winTH);
fill(25);
rect(winX, winY + 24, winW, winH);
}
void update_window()
{
if (dragging == true)
{
// ...
}
// ...
}
First update the order of the windows and calculate its new position. After that draw all the windows in a separate loop:
void draw()
{
background(10);
for (int i = 0; i < wins.length; i ++) {
wins[i].update_window();
}
for (int i = 0; i < wins.length; i ++) {
wins[i].draw_window();
}
}

convert a dynamic circle layout to oval or ellipse in android

I have a image group with three images perpendicularly, those group forms a circle, i have created it as circle view couldn't adjust its width to make it oval, since i have three stacked images one above one i couldn't adjust all those images the code as below's
static int Standard_height = 160;
static int Cam_Size = 50;
static int Segment_Size = 55;
static int TextSize = 10;
private void SetLayoutDesign() {
Layout_Frame.removeAllViews();
Segments = sharedpreferences.getInt(Vars.Selected_Segment_Count, 4);
int imageGap = Segment_Size + 5;
int size = Segment_Size + ((16 - (Segments + 1)));
int imageSize = Cam_Size - Segments;
for (int i = 0; i < Segments; i++) {
// Create some quick TextViews that can be placed.
String StateName = Vars.Segment_State + "_" + i;
int state = sharedpreferences.getInt(StateName, 0);
String TypeName = Vars.Segment_Type + "_" + i;
int type = sharedpreferences.getInt(TypeName, 0);
Segment_Button[i] = new ImageButton(act);
Segment_Name[i] = new TextView(act);
if (type == 0) {
Segment_Name[i].setText((i + 1) + "");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_none);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 1) {
Segment_Name[i].setText((i + 1) + "\nMS");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_ms);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 2) {
Segment_Name[i].setText((i + 1) + "\nFR");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_fr);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 3) {
Segment_Name[i].setText((i + 1) + "\nSR");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_sr);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
}
Segment_Name[i].setGravity(Gravity.CENTER);
Segment_Name[i].setTextColor(Color.WHITE);
Segment_Name[i].setTextSize(TextSize);
Segment_Name[i].setId(Segment_Text_Ids[i]);
Segment_Name[i].setTypeface(null, Typeface.BOLD);
Segment_Button[i].setId(Segment_Ids[i]);
FrameLayout.LayoutParams lp1 = new FrameLayout.LayoutParams(imageSize, imageSize);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(size, size);
lp.gravity = Gravity.CENTER;
lp1.gravity = Gravity.CENTER;
Segment_Button[i].setLayoutParams(lp);
Segment_Button[i].setOnClickListener(this);
Segment_Button[i].setOnLongClickListener(this);
Segment_Name[i].setLayoutParams(lp);
float angleDeg = i * 360.0f / Segments - 90.0f;
float angleRad = (float) (angleDeg * Math.PI / 180.0f);
Segment_Button[i].setTranslationX(Standard_height * (float) Math.cos(angleRad));
Segment_Button[i].setTranslationY(Standard_height * (float) Math.sin(angleRad));
Layout_Frame.addView(Segment_Button[i]);
Segment_Name[i].setTranslationX(Standard_height * (float) Math.cos(angleRad));
Segment_Name[i].setTranslationY(Standard_height * (float) Math.sin(angleRad));
if (Segments % 2 == 0 && Segments != 0) {
Segment_Name[i].setRotation((180 / Segments));
} else {
Segment_Name[i].setRotation(0);
}
Layout_Frame.addView(Segment_Name[i]);
FCam_Button[i] = new ImageButton(act);
FCam_Button[i].setId(FCam_Ids[i]);
String FCamName = Vars.FCam_State + "_" + i;
int FCamState = sharedpreferences.getInt(FCamName, 0);
if (FCamState == 0) {
FCam_Button[i].setBackgroundResource(R.drawable.f_camera_off_image);
} else {
FCam_Button[i].setBackgroundResource(R.drawable.f_camera_on_image);
}
FCam_Button[i].setLayoutParams(lp1);
FCam_Button[i].setOnClickListener(this);
FCam_Button[i].setTranslationX((Standard_height + imageGap) * (float) Math.cos(angleRad));
FCam_Button[i].setTranslationY((Standard_height + imageGap) * (float) Math.sin(angleRad));
FCam_Button[i].setRotation(angleDeg + 90.0f);
Layout_Frame.addView(FCam_Button[i]);
RCam_Button[i] = new ImageButton(act);
RCam_Button[i].setId(RCam_Ids[i]);
String RCamName = Vars.RCam_State + "_" + i;
int RCamState = sharedpreferences.getInt(RCamName, 0);
if (RCamState == 0) {
RCam_Button[i].setBackgroundResource(R.drawable.r_camera_off_image);
} else {
RCam_Button[i].setBackgroundResource(R.drawable.r_camera_on_image);
}
RCam_Button[i].setLayoutParams(lp1);
RCam_Button[i].setOnClickListener(this);
RCam_Button[i].setTranslationX((Standard_height - imageGap) * (float) Math.cos(angleRad));
RCam_Button[i].setTranslationY((Standard_height - imageGap) * (float) Math.sin(angleRad));
RCam_Button[i].setRotation(angleDeg + 90.0f);
Layout_Frame.addView(RCam_Button[i]);
}
if (Segments % 2 == 0 && Segments != 0) {
Layout_Frame.setRotation(-(180 / Segments));
} else {
Layout_Frame.setRotation(0);
}
SetUserLevelControls();
}
This is the current layout
This is the desired layout

Minesweeper draw number of nearby mines

I need to do a Minesweeper game. I have most of the methods down, but I cannot figure out a way to draw the number of mines around a given tile. I have a method that returns the number of mines around that tile, but no such method to actually display that number inside the tile in the game.
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class MyPanel extends JPanel {
private static final long serialVersionUID = 3426940946811133635L;
private static final int GRID_X = 25;
private static final int GRID_Y = 25;
private static final int INNER_CELL_SIZE = 29;
private static final int TOTAL_COLUMNS = 9;
private static final int TOTAL_ROWS = 10; //Last row has only one cell
public int x = -1;
public int y = -1;
public int mouseDownGridX = 0;
public int mouseDownGridY = 0;
private ImageIcon icon;
private static char minefield[][];
public Color[][] colorArray = new Color[TOTAL_COLUMNS][TOTAL_ROWS];
public MyPanel() { //This is the constructor... this code runs first to initialize
if (INNER_CELL_SIZE + (new Random()).nextInt(1) < 1) { //Use of "random" to prevent unwanted Eclipse warning
throw new RuntimeException("INNER_CELL_SIZE must be positive!");
}
if (TOTAL_COLUMNS + (new Random()).nextInt(1) < 2) { //Use of "random" to prevent unwanted Eclipse warning
throw new RuntimeException("TOTAL_COLUMNS must be at least 2!");
}
if (TOTAL_ROWS + (new Random()).nextInt(1) < 3) { //Use of "random" to prevent unwanted Eclipse warning
throw new RuntimeException("TOTAL_ROWS must be at least 3!");
}
for (int x = 0; x < TOTAL_COLUMNS; x++) { //Top row
colorArray[x][0] = Color.LIGHT_GRAY;
}
for (int y = 0; y < TOTAL_ROWS; y++) { //Left column
colorArray[0][y] = Color.LIGHT_GRAY;
}
for (int x = 1; x < TOTAL_COLUMNS; x++) { //The rest of the grid
for (int y = 1; y < TOTAL_ROWS; y++) {
colorArray[x][y] = Color.LIGHT_GRAY;
}
}
minefield = new char [TOTAL_COLUMNS][TOTAL_ROWS];
}
Random rando = new Random();
public static int mines = 10;
public int flags = 10;
public static int flagged = 0;
public void paintComponent(Graphics g) {
super.paintComponent(g);
//Compute interior coordinates
Insets myInsets = getInsets();
int x1 = myInsets.left;
int y1 = myInsets.top;
int x2 = getWidth() - myInsets.right - 1;
int y2 = getHeight() - myInsets.bottom - 1;
int width = x2 - x1;
int height = y2 - y1;
//Paint the background
g.setColor(Color.LIGHT_GRAY);
g.fillRect(x1, y1, width + 1, height + 1);
//Draw the grid minus the bottom row (which has only one cell)
//By default, the grid will be 10x10 (see above: TOTAL_COLUMNS and TOTAL_ROWS)
g.setColor(Color.BLACK);
for (int y = 0; y <= TOTAL_ROWS - 1; y++) {
g.drawLine(x1 + GRID_X, y1 + GRID_Y + (y * (INNER_CELL_SIZE + 1)), x1 + GRID_X + ((INNER_CELL_SIZE + 1) * TOTAL_COLUMNS), y1 + GRID_Y + (y * (INNER_CELL_SIZE + 1)));
}
for (int x = 0; x <= TOTAL_COLUMNS; x++) {
g.drawLine(x1 + GRID_X + (x * (INNER_CELL_SIZE + 1)), y1 + GRID_Y, x1 + GRID_X + (x * (INNER_CELL_SIZE + 1)), y1 + GRID_Y + ((INNER_CELL_SIZE + 1) * (TOTAL_ROWS - 1)));
}
//Paint cell colors
for (int x = 0; x < TOTAL_COLUMNS; x++) {
for (int y = 0; y < TOTAL_ROWS; y++) {
if ((x == 0) || (y != TOTAL_ROWS - 1)) {
Color c = colorArray[x][y];
g.setColor(c);
g.fillRect(x1 + GRID_X + (x * (INNER_CELL_SIZE + 1)) + 1, y1 + GRID_Y + (y * (INNER_CELL_SIZE + 1)) + 1, INNER_CELL_SIZE, INNER_CELL_SIZE);
}
}
}
}
// Places the mines in the field
public void placeMines() {
int minesPlaced = 1;
while (minesPlaced <= mines) {
int x = rando.nextInt(TOTAL_COLUMNS);
int y = rando.nextInt(TOTAL_ROWS-1);
if (minefield[x][y] != '*') {
minefield[x][y] = '*';
minesPlaced++;
}
}
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
bombCheck(i, j);
if (bombCheck(i, j) == 1) {
System.out.println(i + "," + j); // for debugging purposes
}
}
}repaint();
}
//checks a tile, white if there were no mines
public void check (int x, int y) {
colorArray[x][y] = Color.WHITE ;
repaint();
}
// Checks whether this place in the field has a bomb (1) or not (0).
public int bombCheck(int x, int y) {
if (!(x == -1 || y == -1)) {
if (minefield[x][y] == '*') {
return 1;
}
else {
minefield[x][y] = 'c';
return 0;
}
}
else{
return 0;
}
}
// Checks for mines on the 8 other tiles around the target location and returns the number of mines there are.
public int minesAround(int x, int y) {
int mines = 0;
mines += bombCheck(x-1, y-1);
mines += bombCheck(x-1, y);
mines += bombCheck(x-1, y+1);
mines += bombCheck(x, y-1);
mines += bombCheck(x, y+1);
mines += bombCheck(x+1, y-1);
mines += bombCheck(x+1, y);
mines += bombCheck(x+1, y+1);
if (mines > 0) {
return mines;
}
else{
return 0;
}
}
//What I've come up with so far for drawing the number in the tile. Does not work.
public void draw (Graphics g, int n, int x, int y) {
super.paintComponent(g);
g.drawString("" + n + "", x, y);
}
//Recursive method
public void checkAround(int x, int y) {
int minx, miny, maxx, maxy;
check(x,y);
minx = (x <= 0 ? 0 : x - 1);
miny = (y <= 0 ? 0 : y - 1);
maxx = (x >= TOTAL_COLUMNS - 1 ? TOTAL_COLUMNS - 1 : x + 1);
maxy = (y >= TOTAL_ROWS - 2 ? TOTAL_ROWS - 2 : y + 1);
for (int i = minx; i < maxx; i ++) {
for (int j = miny; j <= maxy; j ++) {
if (bombCheck(i,j) == 0 && colorArray[i][j] != Color.WHITE) {
check(i,j);
if (minesAround(i,j) == 0) {
checkAround(i,j);
}
if (minesAround(i,j) == 1) {
draw(getGraphics(),1,i,j); // Does not work.
repaint();
}
}
}
}
}
//Flag
public int checkflag(int x, int y){
int status = 0;
if (!(x == -1 || y == -1)) {
if (colorArray[x][y] == Color.RED) {
status += 1;
}else {
status += 0;
}
}
return status;
}
//Resets field
public void reset() {
for (int i = 0; i < TOTAL_COLUMNS; i++) {
for (int j = 0 ;j < TOTAL_ROWS; j++) {
colorArray[i][j] = Color.LIGHT_GRAY;
minefield[i][j] = ' ';
MyMouseAdapter.f = 1;
repaint();
}
}
placeMines();
}
public int getGridX(int x, int y) {
Insets myInsets = getInsets();
int x1 = myInsets.left;
int y1 = myInsets.top;
x = x - x1 - GRID_X;
y = y - y1 - GRID_Y;
if (x < 0) { //To the left of the grid
return -1;
}
if (y < 0) { //Above the grid
return -1;
}
if ((x % (INNER_CELL_SIZE + 1) == 0) || (y % (INNER_CELL_SIZE + 1) == 0)) { //Coordinate is at an edge; not inside a cell
return -1;
}
x = x / (INNER_CELL_SIZE + 1);
y = y / (INNER_CELL_SIZE + 1);
if (x == 0 && y == TOTAL_ROWS - 1) { //The lower left extra cell
return x;
}
if (x < 0 || x > TOTAL_COLUMNS - 1 || y < 0 || y > TOTAL_ROWS - 2) { //Outside the rest of the grid
return -1;
}
return x;
}
public int getGridY(int x, int y) {
Insets myInsets = getInsets();
int x1 = myInsets.left;
int y1 = myInsets.top;
x = x - x1 - GRID_X;
y = y - y1 - GRID_Y;
if (x < 0) { //To the left of the grid
return -1;
}
if (y < 0) { //Above the grid
return -1;
}
if ((x % (INNER_CELL_SIZE + 1) == 0) || (y % (INNER_CELL_SIZE + 1) == 0)) { //Coordinate is at an edge; not inside a cell
return -1;
}
x = x / (INNER_CELL_SIZE + 1);
y = y / (INNER_CELL_SIZE + 1);
if (x == 0 && y == TOTAL_ROWS - 1) { //The lower left extra cell
return y;
}
if (x < 0 || x > TOTAL_COLUMNS - 1 || y < 0 || y > TOTAL_ROWS - 2) { //Outside the rest of the grid
return -1;
}
return y;
}
public ImageIcon getIcon() {
return icon;
}
public void setIcon(ImageIcon icon) {
this.icon = icon;
}
}
-
import java.awt.Color;
import java.awt.Component;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Random;
import javax.swing.JFrame;
public class MyMouseAdapter extends MouseAdapter {
public static int f = 1;
public void mousePressed(MouseEvent e) {
switch (e.getButton()) {
case 1: //Left mouse button
Component c = e.getComponent();
while (!(c instanceof JFrame)) {
c = c.getParent();
if (c == null) {
return;
}
}
JFrame myFrame = (JFrame) c;
MyPanel myPanel = (MyPanel) myFrame.getContentPane().getComponent(0);
Insets myInsets = myFrame.getInsets();
int x1 = myInsets.left;
int y1 = myInsets.top;
e.translatePoint(-x1, -y1);
int x = e.getX();
int y = e.getY();
myPanel.x = x;
myPanel.y = y;
myPanel.mouseDownGridX = myPanel.getGridX(x, y);
myPanel.mouseDownGridY = myPanel.getGridY(x, y);
myPanel.repaint();
break;
case 3: //Right mouse button
Component c1 = e.getComponent();
while (!(c1 instanceof JFrame)) {
c = c1.getParent();
if (c == null) {
return;
}
}
JFrame myFrame1 = (JFrame)c1;
MyPanel myPanel1 = (MyPanel) myFrame1.getContentPane().getComponent(0); //Can also loop among components to find MyPanel
Insets myInsets1 = myFrame1.getInsets();
int x2 = myInsets1.left;
int y2 = myInsets1.top;
e.translatePoint(-x2, -y2);
int x3 = e.getX();
int y3 = e.getY();
myPanel1.x = x3;
myPanel1.y = y3;
myPanel1.mouseDownGridX = myPanel1.getGridX(x3, y3);
myPanel1.mouseDownGridY = myPanel1.getGridY(x3, y3);
break;
default: //Some other button (2 = Middle mouse button, etc.)
//Do nothing
break;
}
}
public void mouseReleased(MouseEvent e) {
switch (e.getButton()) {
case 1: //Left mouse button
Component c = e.getComponent();
while (!(c instanceof JFrame)) {
c = c.getParent();
if (c == null) {
return;
}
}
JFrame myFrame = (JFrame)c;
MyPanel myPanel = (MyPanel) myFrame.getContentPane().getComponent(0); //Can also loop among components to find MyPanel
Insets myInsets = myFrame.getInsets();
int x1 = myInsets.left;
int y1 = myInsets.top;
e.translatePoint(-x1, -y1);
int x = e.getX();
int y = e.getY();
myPanel.x = x;
myPanel.y = y;
int gridX = myPanel.getGridX(x, y);
int gridY = myPanel.getGridY(x, y);
if ((myPanel.mouseDownGridX == -1) || (myPanel.mouseDownGridY == -1)) {
//Had pressed outside
//Do nothing
} else {
if ((gridX == -1) || (gridY == -1)) {
//Do nothing
}else if (gridX == 0 && gridY == 9) {
myPanel.reset();
} else {
if ((myPanel.mouseDownGridX != gridX) || (myPanel.mouseDownGridY != gridY)) {
//Released the mouse button on a different cell where it was pressed
//Do nothing
} else {
//Released the mouse button on the same cell where it was pressed
if (!(myPanel.mouseDownGridX == -1) || (myPanel.mouseDownGridY == -1)) {
if (!(myPanel.colorArray[gridX][gridY] == Color.RED)) {
if (myPanel.bombCheck(gridX, gridY) == 0) {
myPanel.checkAround(gridX, gridY);
}
else{
myPanel.colorArray[gridX][gridY] = Color.BLACK ;
System.out.println("You've Lost!");
myPanel.reset();
myPanel.repaint();
}
}
}
}
}
}
myPanel.repaint();
break;
case 3: //Right mouse button
Component c1 = e.getComponent();
while (!(c1 instanceof JFrame)) {
c = c1.getParent();
if (c == null) {
return;
}
}
JFrame myFrame1 = (JFrame)c1;
MyPanel myPanel1 = (MyPanel) myFrame1.getContentPane().getComponent(0); //Can also loop among components to find MyPanel
Insets myInsets1 = myFrame1.getInsets();
int x2 = myInsets1.left;
int y2 = myInsets1.top;
e.translatePoint(-x2, -y2);
int x3 = e.getX();
int y3 = e.getY();
myPanel1.x = x3;
myPanel1.y = y3;
int gridX1 = myPanel1.getGridX(x3, y3);
int gridY1 = myPanel1.getGridY(x3, y3);
int flags = 10;
if ((myPanel1.mouseDownGridX == -1) || (myPanel1.mouseDownGridY == -1)) {
//Had pressed outside
//Do nothing
} else {
if ((gridX1 == -1) || (gridY1 == -1)) {
//Is releasing outside
//Do nothing
} else {
if ((myPanel1.mouseDownGridX != gridX1) || (myPanel1.mouseDownGridY != gridY1)) {
}else{
if (!(myPanel1.colorArray[gridX1][gridY1] == Color.WHITE)) {
if (myPanel1.checkflag(gridX1, gridY1) == 0) {
if (!(f > flags)) {
if (myPanel1.bombCheck(gridX1, gridY1) == 1) {
MyPanel.flagged ++;
if (MyPanel.flagged == 10) {
System.out.println("You've Won! Congratulations!");
myPanel1.reset();
myPanel1.colorArray[gridX1][gridY1] = Color.LIGHT_GRAY ;
myPanel1.repaint();
}
}
myPanel1.colorArray[gridX1][gridY1] = Color.RED ;
myPanel1.repaint();
f ++;
}
}
else {
myPanel1.colorArray[gridX1][gridY1] = Color.LIGHT_GRAY ;
myPanel1.repaint();
f --;
}
}
}
}
}
break;
default: //Some other button (2 = Middle mouse button, etc.)
//Do nothing
break;
}
}
}
-
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame myFrame = new JFrame("Color Grid");
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.setLocation(400, 150);
myFrame.setSize(400, 400);
MyPanel myPanel = new MyPanel();
myFrame.add(myPanel);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
myFrame.addMouseListener(myMouseAdapter);
myFrame.setVisible(true);
myPanel.placeMines();
}
}
This is only my first year studying Computer science, but if my intuition is correct, my draw method is drawing the number behind the tiles. These are just my thoughts, I have relatively little to no experience with Java.
In your paintComponent() add something like this:
Font f = new Font("Dialog", Font.PLAIN, 12); // choose a font for the numbers
g.setFont(f);
// Draw cell numbers
for (int x = 0; x < TOTAL_COLUMNS; x++) {
for (int y = 0; y < TOTAL_ROWS; y++) {
if (/* check if the (x,y) cell is uncovered */) {
int around = minesAround(x, y);
g.drawString(String.valueOf(around), /*cell x coord*/, /*cell y coord*/);
}
}
}
Alternatively, you can use an image for each cell number instead of using a string.

GridView Rearange switch by drag and drop

I have a program that creates a Grid and rearranges it by drag-and-droping, first of all everything is functional BUT not the way I wanted it. The must common rearrange is this, you drag an object and when you drop it falls into that position moving all the rest forward until they find the empty space, what I want is more simple; I want the objects to switch with the one that's in the position you dropped it. This is the code of the adapter:
#SuppressLint("WrongCall")
public class DragGridView extends ViewGroup implements View.OnTouchListener,
View.OnClickListener, View.OnLongClickListener {
public static float childRatio = .9f;
protected int colCount, childSize, padding, dpi, scroll = 0;
protected float lastDelta = 0;
protected Handler handler = new Handler();
protected int dragged = -1, lastX = -1, lastY = -1, lastTarget = -1;
protected boolean enabled = true, touching = false;
public static int animT = 150;
protected ArrayList<Integer> newPositions = new ArrayList<Integer>();
protected OnRearrangeListener onRearrangeListener;
protected OnClickListener secondaryOnClickListener;
private OnItemClickListener onItemClickListener;
public interface OnRearrangeListener {
public abstract void onRearrange(int oldIndex, int newIndex);
}
public DragGridView(Context context, AttributeSet attrs) {
super(context, attrs);
setListeners();
handler.removeCallbacks(updateTask);
handler.postAtTime(updateTask, SystemClock.uptimeMillis() + 500);
setChildrenDrawingOrderEnabled(true);
DisplayMetrics metrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
dpi = metrics.densityDpi;
}
protected void setListeners() {
setOnTouchListener(this);
super.setOnClickListener(this);
setOnLongClickListener(this);
}
#Override
public void setOnClickListener(OnClickListener l) {
secondaryOnClickListener = l;
}
protected Runnable updateTask = new Runnable() {
public void run() {
if (dragged != -1) {
if (lastY < padding * 3 && scroll > 0)
scroll -= 20;
else if (lastY > getBottom() - getTop() - (padding * 3)
&& scroll < getMaxScroll())
scroll += 20;
} else if (lastDelta != 0 && !touching) {
scroll += lastDelta;
lastDelta *= .9;
if (Math.abs(lastDelta) < .25)
lastDelta = 0;
}
clampScroll();
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
handler.postDelayed(this, 25);
}
};
#Override
public void addView(View child) {
super.addView(child);
newPositions.add(-1);
};
#Override
public void removeViewAt(int index) {
super.removeViewAt(index);
newPositions.remove(index);
};
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// compute width of view, in dp
float w = (r - l) / (dpi / 160f);
colCount = 2;
int sub = 240;
w -= 280;
while (w > 0) {
colCount++;
w -= sub;
sub += 40;
}
childSize = (r - l) / colCount;
childSize = Math.round(childSize * childRatio);
padding = ((r - l) - (childSize * colCount)) / (colCount + 1);
for (int i = 0; i < getChildCount(); i++)
if (i != dragged) {
Point xy = getCoorFromIndex(i);
getChildAt(i).layout(xy.x, xy.y, xy.x + childSize,
xy.y + childSize);
}
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if (dragged == -1)
return i;
else if (i == childCount - 1)
return dragged;
else if (i >= dragged)
return i + 1;
return i;
}
public int getIndexFromCoor(int x, int y) {
int col = getColOrRowFromCoor(x), row = getColOrRowFromCoor(y + scroll);
if (col == -1 || row == -1)
return -1;
int index = row * colCount + col;
if (index >= getChildCount())
return -1;
return index;
}
protected int getColOrRowFromCoor(int coor) {
coor -= padding;
for (int i = 0; coor > 0; i++) {
if (coor < childSize)
return i;
coor -= (childSize + padding);
}
return -1;
}
protected int getTargetFromCoor(int x, int y) {
if (getColOrRowFromCoor(y + scroll) == -1)
return -1;
int leftPos = getIndexFromCoor(x - (childSize / 4), y);
int rightPos = getIndexFromCoor(x + (childSize / 4), y);
if (leftPos == -1 && rightPos == -1)
return -1;
if (leftPos == rightPos)
return -1;
int target = -1;
if (rightPos > -1)
target = rightPos;
else if (leftPos > -1)
target = leftPos + 1;
if (dragged < target)
return target - 1;
return target;
}
protected Point getCoorFromIndex(int index) {
int col = index % colCount;
int row = index / colCount;
return new Point(padding + (childSize + padding) * col, padding
+ (childSize + padding) * row - scroll);
}
public int getIndexOf(View child) {
for (int i = 0; i < getChildCount(); i++)
if (getChildAt(i) == child)
return i;
return -1;
}
public void onClick(View view) {
if (enabled) {
if (secondaryOnClickListener != null)
secondaryOnClickListener.onClick(view);
if (onItemClickListener != null && getLastIndex() != -1)
onItemClickListener.onItemClick(null,
getChildAt(getLastIndex()), getLastIndex(),
getLastIndex() / colCount);
}
}
public boolean onLongClick(View view) {
if (!enabled)
return false;
int index = getLastIndex();
if (index != -1) {
dragged = index;
animateDragged();
return true;
}
return false;
}
#SuppressLint("WrongCall")
public boolean onTouch(View view, MotionEvent event) {
int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
enabled = true;
lastX = (int) event.getX();
lastY = (int) event.getY();
touching = true;
break;
case MotionEvent.ACTION_MOVE:
int delta = lastY - (int) event.getY();
if (dragged != -1) {
// change draw location of dragged visual
int x = (int) event.getX(), y = (int) event.getY();
int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
getChildAt(dragged).layout(l, t, l + (childSize * 3 / 2),
t + (childSize * 3 / 2));
// check for new target hover
int target = getTargetFromCoor(x, y);
if (lastTarget != target) {
if (target != -1) {
animateGap(target);
lastTarget = target;
}
}
} else {
scroll += delta;
clampScroll();
if (Math.abs(delta) > 2)
enabled = false;
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
}
lastX = (int) event.getX();
lastY = (int) event.getY();
lastDelta = delta;
break;
case MotionEvent.ACTION_UP:
if (dragged != -1) {
View v = getChildAt(dragged);
if (lastTarget != -1)
reorderChildren();
else {
Point xy = getCoorFromIndex(dragged);
v.layout(xy.x, xy.y, xy.x + childSize, xy.y + childSize);
}
v.clearAnimation();
if (v instanceof ImageView)
((ImageView) v).setAlpha(255);
lastTarget = -1;
dragged = -1;
}
touching = false;
break;
}
if (dragged != -1)
return true;
return false;
}
protected void animateDragged() {
View v = getChildAt(dragged);
int x = getCoorFromIndex(dragged).x + childSize / 2, y = getCoorFromIndex(dragged).y
+ childSize / 2;
int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
v.layout(l, t, l + (childSize * 3 / 2), t + (childSize * 3 / 2));
AnimationSet animSet = new AnimationSet(true);
ScaleAnimation scale = new ScaleAnimation(.667f, 1, .667f, 1,
childSize * 3 / 4, childSize * 3 / 4);
scale.setDuration(animT);
AlphaAnimation alpha = new AlphaAnimation(1, .5f);
alpha.setDuration(animT);
animSet.addAnimation(scale);
animSet.addAnimation(alpha);
animSet.setFillEnabled(true);
animSet.setFillAfter(true);
v.clearAnimation();
v.startAnimation(animSet);
}
protected void animateGap(int target) {
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
if (i == dragged)
continue;
int newPos = i;
if (dragged < target && i >= dragged + 1 && i <= target)
newPos--;
else if (target < dragged && i >= target && i < dragged)
newPos++;
int oldPos = i;
if (newPositions.get(i) != -1)
oldPos = newPositions.get(i);
if (oldPos == newPos)
continue;
Point oldXY = getCoorFromIndex(oldPos);
Point newXY = getCoorFromIndex(newPos);
Point oldOffset = new Point(oldXY.x - v.getLeft(), oldXY.y
- v.getTop());
Point newOffset = new Point(newXY.x - v.getLeft(), newXY.y
- v.getTop());
TranslateAnimation translate = new TranslateAnimation(
Animation.ABSOLUTE, oldOffset.x, Animation.ABSOLUTE,
newOffset.x, Animation.ABSOLUTE, oldOffset.y,
Animation.ABSOLUTE, newOffset.y);
translate.setDuration(animT);
translate.setFillEnabled(true);
translate.setFillAfter(true);
v.clearAnimation();
v.startAnimation(translate);
newPositions.set(i, newPos);
}
}
protected void reorderChildren() {
if (onRearrangeListener != null)
onRearrangeListener.onRearrange(dragged, lastTarget);
ArrayList<View> children = new ArrayList<View>();
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).clearAnimation();
children.add(getChildAt(i));
}
removeAllViews();
while (dragged != lastTarget)
if (lastTarget == children.size())
{
children.add(children.remove(dragged));
dragged = lastTarget;
} else if (dragged < lastTarget)
{
Collections.swap(children, dragged, dragged + 1);
dragged++;
} else if (dragged > lastTarget)
{
Collections.swap(children, dragged, dragged - 1);
dragged--;
}
for (int i = 0; i < children.size(); i++) {
newPositions.set(i, -1);
addView(children.get(i));
}
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
}
#SuppressLint("WrongCall")
public void scrollToTop() {
scroll = 0;
}
public void scrollToBottom() {
scroll = Integer.MAX_VALUE;
clampScroll();
}
protected void clampScroll() {
int stretch = 3, overreach = getHeight() / 2;
int max = getMaxScroll();
max = Math.max(max, 0);
if (scroll < -overreach) {
scroll = -overreach;
lastDelta = 0;
} else if (scroll > max + overreach) {
scroll = max + overreach;
lastDelta = 0;
} else if (scroll < 0) {
if (scroll >= -stretch)
scroll = 0;
else if (!touching)
scroll -= scroll / stretch;
} else if (scroll > max) {
if (scroll <= max + stretch)
scroll = max;
else if (!touching)
scroll += (max - scroll) / stretch;
}
}
protected int getMaxScroll() {
int rowCount = (int) Math.ceil((double) getChildCount() / colCount), max = rowCount
* childSize + (rowCount + 1) * padding - getHeight();
return max;
}
public int getLastIndex() {
return getIndexFromCoor(lastX, lastY);
}
public void setOnRearrangeListener(OnRearrangeListener l) {
this.onRearrangeListener = l;
}
public void setOnItemClickListener(OnItemClickListener l) {
this.onItemClickListener = l;
}
}
The Methods I think I have to change are AnimateGap and reorderChildren, but don't know how to do it exactly.

How to import .java library in IntelliJ (folder of .java files)

I am a new programmer.
Here, I am trying to import a library (com.digitalmodular).
What I want to do is run the java program in here
package demos;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Arrays;
import com.digitalmodular.utilities.RandomFunctions;
import com.digitalmodular.utilities.gui.ImageFunctions;
import com.digitalmodular.utilities.swing.window.PixelImage;
import com.digitalmodular.utilities.swing.window.PixelWindow;
/**
* #author jeronimus
*/
// Date 2014-02-28
public class AllColorDiffusion extends PixelWindow implements Runnable {
private static final int CHANNEL_BITS = 7;
public static void main(String[] args) {
int bits = CHANNEL_BITS * 3;
int heightBits = bits / 2;
int widthBits = bits - heightBits;
new AllColorDiffusion(CHANNEL_BITS, 1 << widthBits, 1 << heightBits);
}
private final int width;
private final int height;
private final int channelBits;
private final int channelSize;
private PixelImage img;
private javax.swing.Timer timer;
private boolean[] colorCube;
private long[] foundColors;
private boolean[] queued;
private int[] queue;
private int queuePointer = 0;
private int remaining;
public AllColorDiffusion(int channelBits, int width, int height) {
super(1024, 1024 * height / width);
RandomFunctions.RND.setSeed(0);
this.width = width;
this.height = height;
this.channelBits = channelBits;
channelSize = 1 << channelBits;
}
#Override
public void initialized() {
img = new PixelImage(width, height);
colorCube = new boolean[channelSize * channelSize * channelSize];
foundColors = new long[channelSize * channelSize * channelSize];
queued = new boolean[width * height];
queue = new int[width * height];
for (int i = 0; i < queue.length; i++)
queue[i] = i;
new Thread(this).start();
}
#Override
public void resized() {}
#Override
public void run() {
timer = new javax.swing.Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
draw();
}
});
while (true) {
img.clear(0);
init();
render();
}
// System.exit(0);
}
private void init() {
RandomFunctions.RND.setSeed(0);
Arrays.fill(colorCube, false);
Arrays.fill(queued, false);
remaining = width * height;
// Initial seeds (need to be the darkest colors, because of the darkest
// neighbor color search algorithm.)
setPixel(width / 2 + height / 2 * width, 0);
remaining--;
}
private void render() {
timer.start();
for (; remaining > 0; remaining--) {
int point = findPoint();
int color = findColor(point);
setPixel(point, color);
}
timer.stop();
draw();
try {
ImageFunctions.savePNG(System.currentTimeMillis() + ".png", img.image);
}
catch (IOException e1) {
e1.printStackTrace();
}
}
void draw() {
g.drawImage(img.image, 0, 0, getWidth(), getHeight(), 0, 0, width, height, null);
repaintNow();
}
private int findPoint() {
while (true) {
// Time to reshuffle?
if (queuePointer == 0) {
for (int i = queue.length - 1; i > 0; i--) {
int j = RandomFunctions.RND.nextInt(i);
int temp = queue[i];
queue[i] = queue[j];
queue[j] = temp;
queuePointer = queue.length;
}
}
if (queued[queue[--queuePointer]])
return queue[queuePointer];
}
}
private int findColor(int point) {
int x = point & width - 1;
int y = point / width;
// Calculate the reference color as the average of all 8-connected
// colors.
int r = 0;
int g = 0;
int b = 0;
int n = 0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
point = (x + i & width - 1) + width * (y + j & height - 1);
if (img.pixels[point] != 0) {
int pixel = img.pixels[point];
r += pixel >> 24 - channelBits & channelSize - 1;
g += pixel >> 16 - channelBits & channelSize - 1;
b += pixel >> 8 - channelBits & channelSize - 1;
n++;
}
}
}
r /= n;
g /= n;
b /= n;
// Find a color that is preferably darker but not too far from the
// original. This algorithm might fail to take some darker colors at the
// start, and when the image is almost done the size will become really
// huge because only bright reference pixels are being searched for.
// This happens with a probability of 50% with 6 channelBits, and more
// with higher channelBits values.
//
// Try incrementally larger distances from reference color.
for (int size = 2; size <= channelSize; size *= 2) {
n = 0;
// Find all colors in a neighborhood from the reference color (-1 if
// already taken).
for (int ri = r - size; ri <= r + size; ri++) {
if (ri < 0 || ri >= channelSize)
continue;
int plane = ri * channelSize * channelSize;
int dr = Math.abs(ri - r);
for (int gi = g - size; gi <= g + size; gi++) {
if (gi < 0 || gi >= channelSize)
continue;
int slice = plane + gi * channelSize;
int drg = Math.max(dr, Math.abs(gi - g));
int mrg = Math.min(ri, gi);
for (int bi = b - size; bi <= b + size; bi++) {
if (bi < 0 || bi >= channelSize)
continue;
if (Math.max(drg, Math.abs(bi - b)) > size)
continue;
if (!colorCube[slice + bi])
foundColors[n++] = Math.min(mrg, bi) << channelBits * 3 | slice + bi;
}
}
}
if (n > 0) {
// Sort by distance from origin.
Arrays.sort(foundColors, 0, n);
// Find a random color amongst all colors equally distant from
// the origin.
int lowest = (int)(foundColors[0] >> channelBits * 3);
for (int i = 1; i < n; i++) {
if (foundColors[i] >> channelBits * 3 > lowest) {
n = i;
break;
}
}
int nextInt = RandomFunctions.RND.nextInt(n);
return (int)(foundColors[nextInt] & (1 << channelBits * 3) - 1);
}
}
return -1;
}
private void setPixel(int point, int color) {
int b = color & channelSize - 1;
int g = color >> channelBits & channelSize - 1;
int r = color >> channelBits * 2 & channelSize - 1;
img.pixels[point] = 0xFF000000 | ((r << 8 | g) << 8 | b) << 8 - channelBits;
colorCube[color] = true;
int x = point & width - 1;
int y = point / width;
queued[point] = false;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
point = (x + i & width - 1) + width * (y + j & height - 1);
if (img.pixels[point] == 0) {
queued[point] = true;
}
}
}
}
}
The thing is, I cant figure out how to import the library into IntelliJ. I have tried importing the library from Project Structure->Modules->Dependencies->Library->Java but failed. It appears that all the files in the given library are .java files, not .jar files
How should I import the library? Do I need to compile the whole library first? If yes, how?
This is my first question on this site, so my question may not be so clear :P
try
go to project settings -> Platform Settings -> SDKs -> Sourcepath (in the right panel) and add your downloaded zip -> Apply -> OK

Categories