v0.7.5e: rewrote wnditem button layout code to fix various bugs

This commit is contained in:
Evan Debenham 2019-10-23 20:42:17 -04:00
parent 9f8791978a
commit db8eb884f6

View File

@ -32,7 +32,6 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
public class WndItem extends Window { public class WndItem extends Window {
@ -87,10 +86,9 @@ public class WndItem extends Window {
add( info ); add( info );
float y = info.top() + info.height() + GAP; float y = info.top() + info.height() + GAP;
float x = 0;
if (Dungeon.hero.isAlive() && options) { if (Dungeon.hero.isAlive() && options) {
ArrayList<RedButton> line = new ArrayList<>(); ArrayList<RedButton> buttons = new ArrayList<>();
for (final String action:item.actions( Dungeon.hero )) { for (final String action:item.actions( Dungeon.hero )) {
RedButton btn = new RedButton( Messages.get(item, "ac_" + action), 8 ) { RedButton btn = new RedButton( Messages.get(item, "ac_" + action), 8 ) {
@ -102,74 +100,109 @@ public class WndItem extends Window {
} }
}; };
btn.setSize( btn.reqWidth(), BUTTON_HEIGHT ); btn.setSize( btn.reqWidth(), BUTTON_HEIGHT );
if (x + btn.width() > width || line.size() == 3) { buttons.add(btn);
layoutButtons(line, width - x, y);
x = 0;
y += BUTTON_HEIGHT + 1;
line = new ArrayList<>();
}
x++;
add( btn ); add( btn );
line.add( btn );
if (action.equals(item.defaultAction)) { if (action.equals(item.defaultAction)) {
btn.textColor( TITLE_COLOR ); btn.textColor( TITLE_COLOR );
} }
x += btn.width();
} }
layoutButtons(line, width - x, y); y = layoutButtons(buttons, width, y);
} }
resize( width, (int)(y + (x > 0 ? BUTTON_HEIGHT : 0)) ); resize( width, (int)(y) );
} }
//this method assumes a max of 3 buttons per line private static float layoutButtons(ArrayList<RedButton> buttons, float width, float y){
//FIXME: this is really messy for just trying to make buttons fill the window. Gotta be a cleaner way. ArrayList<RedButton> curRow = new ArrayList<>();
private static void layoutButtons(ArrayList<RedButton> line, float extraWidth, float y){ float widthLeftThisRow = width;
if (line == null || line.size() == 0 || extraWidth == 0) return;
if (line.size() == 1){
line.get(0).setSize(line.get(0).width()+extraWidth, BUTTON_HEIGHT);
line.get(0).setPos( 0 , y );
return;
}
ArrayList<RedButton> lineByWidths = new ArrayList<>(line);
Collections.sort(lineByWidths, widthComparator);
RedButton smallest, middle, largest;
smallest = lineByWidths.get(0);
middle = lineByWidths.get(1);
largest = null;
if (lineByWidths.size() == 3) {
largest = lineByWidths.get(2);
}
float btnDiff = middle.width() - smallest.width(); while( !buttons.isEmpty() ){
smallest.setSize(smallest.width() + Math.min(btnDiff, extraWidth), BUTTON_HEIGHT); RedButton btn = buttons.get(0);
extraWidth -= btnDiff;
if (extraWidth > 0) { widthLeftThisRow -= btn.width();
if (largest == null) { if (curRow.isEmpty()) {
smallest.setSize(smallest.width() + extraWidth / 2, BUTTON_HEIGHT); curRow.add(btn);
middle.setSize(middle.width() + extraWidth / 2, BUTTON_HEIGHT); buttons.remove(btn);
} else { } else {
btnDiff = largest.width() - smallest.width(); widthLeftThisRow -= 1;
smallest.setSize(smallest.width() + Math.min(btnDiff, extraWidth/2), BUTTON_HEIGHT); if (widthLeftThisRow >= 0) {
middle.setSize(middle.width() + Math.min(btnDiff, extraWidth/2), BUTTON_HEIGHT); curRow.add(btn);
extraWidth -= btnDiff*2; buttons.remove(btn);
if (extraWidth > 0){ }
smallest.setSize(smallest.width() + extraWidth / 3, BUTTON_HEIGHT); }
middle.setSize(middle.width() + extraWidth / 3, BUTTON_HEIGHT);
largest.setSize(largest.width() + extraWidth / 3, BUTTON_HEIGHT); //layout current row. Currently forces a max of 3 buttons but can work with more
if (buttons.isEmpty() || widthLeftThisRow <= 0 || curRow.size() >= 3){
//re-use this variable for laying out the buttons
widthLeftThisRow = width - (curRow.size()-1);
for (RedButton b : curRow){
widthLeftThisRow -= b.width();
}
//while we still have space in this row, find the shortest button(s) and extend them
while (widthLeftThisRow > 0){
ArrayList<RedButton> shortest = new ArrayList<>();
RedButton secondShortest = null;
for (RedButton b : curRow) {
if (shortest.isEmpty()) {
shortest.add(b);
} else {
if (b.width() < shortest.get(0).width()) {
secondShortest = shortest.get(0);
shortest.clear();
shortest.add(b);
} else if (b.width() == shortest.get(0).width()) {
shortest.add(b);
} else if (secondShortest == null || secondShortest.width() > b.width()){
secondShortest = b;
} }
} }
} }
float x = 0; float widthToGrow;
for (RedButton btn : line){
btn.setPos( x , y ); if (secondShortest == null){
x += btn.width()+1; widthToGrow = widthLeftThisRow / shortest.size();
widthLeftThisRow = 0;
} else {
widthToGrow = secondShortest.width() - shortest.get(0).width();
if ((widthToGrow * shortest.size()) >= widthLeftThisRow){
widthToGrow = widthLeftThisRow / shortest.size();
widthLeftThisRow = 0;
} else {
widthLeftThisRow -= widthToGrow * shortest.size();
} }
} }
for (RedButton toGrow : shortest){
toGrow.setRect(0, 0, toGrow.width()+widthToGrow, toGrow.height());
}
}
//finally set positions
float x = 0;
for (RedButton b : curRow){
b.setRect(x, y, b.width(), b.height());
x += b.width() + 1;
}
//move to next line and reset variables
y += BUTTON_HEIGHT+1;
widthLeftThisRow = width;
curRow.clear();
}
}
return y - 1;
}
@Override @Override
public void hide() { public void hide() {
super.hide(); super.hide();