Merge pull request #7925 from AUTOMATIC1111/revert-7601-aspect_ratio_sliders
Revert "Aspect ratio sliders"
This commit is contained in:
commit
f04f4b28a2
5 changed files with 2 additions and 517 deletions
|
@ -1,259 +0,0 @@
|
||||||
/* This is a basic library that allows controlling elements that take some form of user input.
|
|
||||||
|
|
||||||
This was previously written in typescript, where all controllers implemented an interface. Not
|
|
||||||
all methods were needed in all the controllers, but it was done to keep a common interface, so
|
|
||||||
your main app can serve as a controller of controllers.
|
|
||||||
|
|
||||||
These controllers were built to work on the shapes of html elements that gradio components use.
|
|
||||||
|
|
||||||
There may be some notes in it that only applied to my use case, but I left them to help others
|
|
||||||
along.
|
|
||||||
|
|
||||||
You will need the parent element for these to work.
|
|
||||||
The parent element can be defined as the element (div) that gets the element id when assigning
|
|
||||||
an element id to a gradio component.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
gr.TextBox(value="...", elem_id="THISID")
|
|
||||||
|
|
||||||
Basic usage, grab an element that is the parent container for the component.
|
|
||||||
|
|
||||||
Send it in to the class, like a function, don't forget the "new" keyword so it calls the constructor
|
|
||||||
and sends back a new object.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
let txt2imgPrompt = new TextComponentController(gradioApp().querySelector("#txt2img_prompt"))
|
|
||||||
|
|
||||||
Then use the getVal() method to get the value, or use the setVal(myValue) method to set the value.
|
|
||||||
|
|
||||||
Input types that are groups, like Checkbox groups (not individual checkboxes), take in an array of values.
|
|
||||||
|
|
||||||
Checkbox group has to reset all values to False (unchecked), then set the values in your array to true (checked).
|
|
||||||
If you don't hold a reference to the values (the labels in string format), you can acquire them using the getVal() method.
|
|
||||||
*/
|
|
||||||
class DropdownComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.childSelector = this.element.querySelector('select');
|
|
||||||
this.children = new Map();
|
|
||||||
Array.from(this.childSelector.querySelectorAll('option')).forEach(opt => this.children.set(opt.value, opt));
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.childSelector.value;
|
|
||||||
}
|
|
||||||
updateVal(optionElement) {
|
|
||||||
optionElement.selected = true;
|
|
||||||
}
|
|
||||||
setVal(name) {
|
|
||||||
this.updateVal(this.children.get(name));
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.childSelector.dispatchEvent(new Event("change"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class CheckboxComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.child = this.element.querySelector('input');
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.child.checked;
|
|
||||||
}
|
|
||||||
updateVal(checked) {
|
|
||||||
this.child.checked = checked;
|
|
||||||
}
|
|
||||||
setVal(checked) {
|
|
||||||
this.updateVal(checked);
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.child.dispatchEvent(new Event("change"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class CheckboxGroupComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
//this.checkBoxes = new Object;
|
|
||||||
this.children = new Map();
|
|
||||||
Array.from(this.element.querySelectorAll('input')).forEach(input => this.children.set(input.nextElementSibling.innerText, input));
|
|
||||||
/* element id gets use fieldset, grab all inputs (the bool val) get the userfriendly label, use as key, put bool value in mapping */
|
|
||||||
//Array.from(this.component.querySelectorAll("input")).forEach( _input => this.checkBoxes[_input.nextElementSibling.innerText] = _input)
|
|
||||||
/*Checkboxgroup structure
|
|
||||||
<fieldset>
|
|
||||||
<div> css makes translucent
|
|
||||||
<span>
|
|
||||||
serves as label for component
|
|
||||||
</span>
|
|
||||||
<div data-testid='checkbox-group'> container for checkboxes
|
|
||||||
<label>
|
|
||||||
<input type=checkbox>
|
|
||||||
<span>checkbox words</span>
|
|
||||||
</label>
|
|
||||||
...
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
updateVal(label) {
|
|
||||||
/*********
|
|
||||||
calls updates using a throttle or else the backend does not get updated properly
|
|
||||||
* ********/
|
|
||||||
setTimeout(() => this.conditionalToggle(true, this.children.get(label)), 2);
|
|
||||||
}
|
|
||||||
setVal(labels) {
|
|
||||||
/* Handles reset and updates all in array to true */
|
|
||||||
this.reupdateVals();
|
|
||||||
labels.forEach(l => this.updateVal(l));
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
//return the list of values that are true
|
|
||||||
return [...this.children].filter(([k, v]) => v.checked).map(arr => arr[0]);
|
|
||||||
}
|
|
||||||
reupdateVals() {
|
|
||||||
/**************
|
|
||||||
* for reupdating all vals, first set to false
|
|
||||||
**************/
|
|
||||||
this.children.forEach(inputChild => this.conditionalToggle(false, inputChild));
|
|
||||||
}
|
|
||||||
conditionalToggle(desiredVal, inputChild) {
|
|
||||||
//This method behaves like 'set this value to this'
|
|
||||||
//Using element.checked = true/false, does not register the change, even if you called change afterwards,
|
|
||||||
// it only sets what it looks like in our case, because there is no form submit, a person then has to click on it twice.
|
|
||||||
//Options are to use .click() or dispatch an event
|
|
||||||
if (desiredVal != inputChild.checked) {
|
|
||||||
inputChild.dispatchEvent(new Event("change")); //using change event instead of click, in case browser ad-blockers blocks the click method
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eventHandler(checkbox) {
|
|
||||||
checkbox.dispatchEvent(new Event("change"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class RadioComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.children = new Map();
|
|
||||||
Array.from(this.element.querySelectorAll("input")).forEach(input => this.children.set(input.value, input));
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
//radio groups have a single element that's checked is true
|
|
||||||
// as array arr k,v pair element.checked ) -> array of len(1) with [k,v] so either [0] [1].value
|
|
||||||
return [...this.children].filter(([l, e]) => e.checked)[0][0];
|
|
||||||
//return Array.from(this.children).filter( ([label, input]) => input.checked)[0][1].value
|
|
||||||
}
|
|
||||||
updateVal(child) {
|
|
||||||
this.eventHandler(child);
|
|
||||||
}
|
|
||||||
setVal(name) {
|
|
||||||
//radio will trigger all false except the one that get the event change
|
|
||||||
//to keep the api similar, other methods are still called
|
|
||||||
this.updateVal(this.children.get(name));
|
|
||||||
}
|
|
||||||
eventHandler(child) {
|
|
||||||
child.dispatchEvent(new Event("change"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class NumberComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.childNumField = element.querySelector('input[type=number]');
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.childNumField.value;
|
|
||||||
}
|
|
||||||
updateVal(text) {
|
|
||||||
this.childNumField.value = text;
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.element.dispatchEvent(new Event("input"));
|
|
||||||
}
|
|
||||||
setVal(text) {
|
|
||||||
this.updateVal(text);
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class SliderComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.childNumField = this.element.querySelector('input[type=number]');
|
|
||||||
this.childRangeField = this.element.querySelector('input[type=range]');
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.childNumField.value;
|
|
||||||
}
|
|
||||||
updateVal(text) {
|
|
||||||
//both are not needed, either works, both are left in so one is a fallback in case of gradio changes
|
|
||||||
this.childNumField.value = text;
|
|
||||||
this.childRangeField.value = text;
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.element.dispatchEvent(new Event("input"));
|
|
||||||
this.childNumField.dispatchEvent(new Event("input"));
|
|
||||||
this.childRangeField.dispatchEvent(new Event("input"));
|
|
||||||
}
|
|
||||||
setVal(text) {
|
|
||||||
this.updateVal(text);
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class TextComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.child = element.querySelector('textarea');
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.child.value;
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.element.dispatchEvent(new Event("input"));
|
|
||||||
this.child.dispatchEvent(new Event("change"));
|
|
||||||
//Workaround to solve no target with v(o) on eventhandler, define my own target
|
|
||||||
let ne = new Event("input");
|
|
||||||
Object.defineProperty(ne, "target", { value: this.child });
|
|
||||||
this.child.dispatchEvent(ne);
|
|
||||||
}
|
|
||||||
updateVal(text) {
|
|
||||||
this.child.value = text;
|
|
||||||
}
|
|
||||||
appendValue(text) {
|
|
||||||
//might add delimiter option
|
|
||||||
this.child.value += ` ${text}`;
|
|
||||||
}
|
|
||||||
setVal(text, append = false) {
|
|
||||||
if (append) {
|
|
||||||
this.appendValue(text);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.updateVal(text);
|
|
||||||
}
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class JsonComponentController extends TextComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
super(element);
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return JSON.parse(this.child.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class ColorComponentController {
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element;
|
|
||||||
this.child = this.element.querySelector('input[type=color]');
|
|
||||||
}
|
|
||||||
updateVal(text) {
|
|
||||||
this.child.value = text;
|
|
||||||
}
|
|
||||||
getVal() {
|
|
||||||
return this.child.value;
|
|
||||||
}
|
|
||||||
setVal(text) {
|
|
||||||
this.updateVal(text);
|
|
||||||
this.eventHandler();
|
|
||||||
}
|
|
||||||
eventHandler() {
|
|
||||||
this.child.dispatchEvent(new Event("input"));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,181 +0,0 @@
|
||||||
class AspectRatioSliderController {
|
|
||||||
constructor(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod) {
|
|
||||||
//References
|
|
||||||
this.widthSlider = new SliderComponentController(widthSlider);
|
|
||||||
this.heightSlider = new SliderComponentController(heightSlider);
|
|
||||||
this.ratioSource = new DropdownComponentController(ratioSource);
|
|
||||||
this.roundingSource = new CheckboxComponentController(roundingSource);
|
|
||||||
this.roundingMethod = new RadioComponentController(roundingMethod);
|
|
||||||
this.roundingIndicatorBadge = document.createElement("div");
|
|
||||||
// Badge implementation
|
|
||||||
this.roundingIndicatorBadge.innerText = "📐";
|
|
||||||
this.roundingIndicatorBadge.classList.add("rounding-badge");
|
|
||||||
this.ratioSource.element.appendChild(this.roundingIndicatorBadge);
|
|
||||||
// Check initial value of ratioSource to set badge visbility
|
|
||||||
let initialRatio = this.ratioSource.getVal();
|
|
||||||
if (!initialRatio.includes(":")) {
|
|
||||||
this.roundingIndicatorBadge.style.display = "none";
|
|
||||||
}
|
|
||||||
//Adjust badge icon if rounding is on
|
|
||||||
if (this.roundingSource.getVal()) {
|
|
||||||
//this.roundingIndicatorBadge.classList.add("active");
|
|
||||||
this.roundingIndicatorBadge.innerText = "📏";
|
|
||||||
}
|
|
||||||
//Make badge clickable to toggle setting
|
|
||||||
this.roundingIndicatorBadge.addEventListener("click", () => {
|
|
||||||
this.roundingSource.setVal(!this.roundingSource.getVal());
|
|
||||||
});
|
|
||||||
//Make rounding setting toggle badge text and style if setting changes
|
|
||||||
this.roundingSource.child.addEventListener("change", () => {
|
|
||||||
if (this.roundingSource.getVal()) {
|
|
||||||
//this.roundingIndicatorBadge.classList.add("active");
|
|
||||||
this.roundingIndicatorBadge.innerText = "📏";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//this.roundingIndicatorBadge.classList.remove("active");
|
|
||||||
this.roundingIndicatorBadge.innerText = "📐";
|
|
||||||
}
|
|
||||||
this.adjustStepSize();
|
|
||||||
});
|
|
||||||
//Other event listeners
|
|
||||||
this.widthSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); });
|
|
||||||
this.widthSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); });
|
|
||||||
this.heightSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); });
|
|
||||||
this.heightSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); });
|
|
||||||
this.ratioSource.childSelector.addEventListener("change", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
//Check and toggle display of badge conditionally on dropdown selection
|
|
||||||
if (!this.ratioSource.getVal().includes(":")) {
|
|
||||||
this.roundingIndicatorBadge.style.display = 'none';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.roundingIndicatorBadge.style.display = 'block';
|
|
||||||
}
|
|
||||||
this.adjustStepSize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resize(dimension) {
|
|
||||||
//For moving slider or number field
|
|
||||||
let val = this.ratioSource.getVal();
|
|
||||||
if (!val.includes(":")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let [width, height] = val.split(":").map(Number);
|
|
||||||
let ratio = width / height;
|
|
||||||
if (dimension == 'width') {
|
|
||||||
let newHeight = parseInt(this.widthSlider.getVal()) / ratio;
|
|
||||||
if (this.roundingSource.getVal()) {
|
|
||||||
switch (this.roundingMethod.getVal()) {
|
|
||||||
case 'Round':
|
|
||||||
newHeight = Math.round(newHeight / 8) * 8;
|
|
||||||
break;
|
|
||||||
case 'Ceiling':
|
|
||||||
newHeight = Math.ceil(newHeight / 8) * 8;
|
|
||||||
break;
|
|
||||||
case 'Floor':
|
|
||||||
newHeight = Math.floor(newHeight / 8) * 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.heightSlider.setVal(newHeight.toString());
|
|
||||||
}
|
|
||||||
else if (dimension == "height") {
|
|
||||||
let newWidth = parseInt(this.heightSlider.getVal()) * ratio;
|
|
||||||
if (this.roundingSource.getVal()) {
|
|
||||||
switch (this.roundingMethod.getVal()) {
|
|
||||||
case 'Round':
|
|
||||||
newWidth = Math.round(newWidth / 8) * 8;
|
|
||||||
break;
|
|
||||||
case 'Ceiling':
|
|
||||||
newWidth = Math.ceil(newWidth / 8) * 8;
|
|
||||||
break;
|
|
||||||
case 'Floor':
|
|
||||||
newWidth = Math.floor(newWidth / 8) * 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.widthSlider.setVal(newWidth.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adjustStepSize() {
|
|
||||||
/* Sets scales/precision/rounding steps;*/
|
|
||||||
let val = this.ratioSource.getVal();
|
|
||||||
if (!val.includes(":")) {
|
|
||||||
//If ratio unlocked
|
|
||||||
this.widthSlider.childRangeField.step = "8";
|
|
||||||
this.widthSlider.childRangeField.min = "64";
|
|
||||||
this.widthSlider.childNumField.step = "8";
|
|
||||||
this.widthSlider.childNumField.min = "64";
|
|
||||||
this.heightSlider.childRangeField.step = "8";
|
|
||||||
this.heightSlider.childRangeField.min = "64";
|
|
||||||
this.heightSlider.childNumField.step = "8";
|
|
||||||
this.heightSlider.childNumField.min = "64";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Format string and calculate step sizes
|
|
||||||
let [width, height] = val.split(":").map(Number);
|
|
||||||
let decimalPlaces = (width.toString().split(".")[1] || []).length;
|
|
||||||
//keep upto 6 decimal points of precision of ratio
|
|
||||||
//euclidean gcd does not support floats, so we scale it up
|
|
||||||
decimalPlaces = decimalPlaces > 6 ? 6 : decimalPlaces;
|
|
||||||
let gcd = this.gcd(width * 10 ** decimalPlaces, height * 10 ** decimalPlaces) / 10 ** decimalPlaces;
|
|
||||||
let stepSize = 8 * height / gcd;
|
|
||||||
let stepSizeOther = 8 * width / gcd;
|
|
||||||
if (this.roundingSource.getVal()) {
|
|
||||||
//If rounding is on set/keep default stepsizes
|
|
||||||
this.widthSlider.childRangeField.step = "8";
|
|
||||||
this.widthSlider.childRangeField.min = "64";
|
|
||||||
this.widthSlider.childNumField.step = "8";
|
|
||||||
this.widthSlider.childNumField.min = "64";
|
|
||||||
this.heightSlider.childRangeField.step = "8";
|
|
||||||
this.heightSlider.childRangeField.min = "64";
|
|
||||||
this.heightSlider.childNumField.step = "8";
|
|
||||||
this.heightSlider.childNumField.min = "64";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//if rounding is off, set step sizes so they enforce snapping
|
|
||||||
//min is changed, because it offsets snap positions
|
|
||||||
this.widthSlider.childRangeField.step = stepSizeOther.toString();
|
|
||||||
this.widthSlider.childRangeField.min = stepSizeOther.toString();
|
|
||||||
this.widthSlider.childNumField.step = stepSizeOther.toString();
|
|
||||||
this.widthSlider.childNumField.min = stepSizeOther.toString();
|
|
||||||
this.heightSlider.childRangeField.step = stepSize.toString();
|
|
||||||
this.heightSlider.childRangeField.min = stepSize.toString();
|
|
||||||
this.heightSlider.childNumField.step = stepSize.toString();
|
|
||||||
this.heightSlider.childNumField.min = stepSize.toString();
|
|
||||||
}
|
|
||||||
let currentWidth = parseInt(this.widthSlider.getVal());
|
|
||||||
//Rounding treated kinda like pythons divmod
|
|
||||||
let stepsTaken = Math.round(currentWidth / stepSizeOther);
|
|
||||||
//this snaps it to closest rule matches (rules being html step points, and ratio)
|
|
||||||
let newWidth = stepsTaken * stepSizeOther;
|
|
||||||
this.widthSlider.setVal(newWidth.toString());
|
|
||||||
this.heightSlider.setVal(Math.round(newWidth / (width / height)).toString());
|
|
||||||
}
|
|
||||||
gcd(a, b) {
|
|
||||||
//euclidean gcd
|
|
||||||
if (b === 0) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return this.gcd(b, a % b);
|
|
||||||
}
|
|
||||||
static observeStartup(widthSliderId, heightSliderId, ratioSourceId, roundingSourceId, roundingMethodId) {
|
|
||||||
let observer = new MutationObserver(() => {
|
|
||||||
let widthSlider = document.querySelector("gradio-app").shadowRoot.getElementById(widthSliderId);
|
|
||||||
let heightSlider = document.querySelector("gradio-app").shadowRoot.getElementById(heightSliderId);
|
|
||||||
let ratioSource = document.querySelector("gradio-app").shadowRoot.getElementById(ratioSourceId);
|
|
||||||
let roundingSource = document.querySelector("gradio-app").shadowRoot.getElementById(roundingSourceId);
|
|
||||||
let roundingMethod = document.querySelector("gradio-app").shadowRoot.getElementById(roundingMethodId);
|
|
||||||
if (widthSlider && heightSlider && ratioSource && roundingSource && roundingMethod) {
|
|
||||||
observer.disconnect();
|
|
||||||
new AspectRatioSliderController(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
observer.observe(gradioApp(), { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
//Register mutation observer for self start-up;
|
|
||||||
AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method");
|
|
||||||
AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method");
|
|
||||||
});
|
|
|
@ -139,24 +139,6 @@ ui_reorder_categories = [
|
||||||
"scripts",
|
"scripts",
|
||||||
]
|
]
|
||||||
|
|
||||||
aspect_ratio_defaults = [
|
|
||||||
"🔓",
|
|
||||||
"1:1",
|
|
||||||
"3:2",
|
|
||||||
"4:3",
|
|
||||||
"5:4",
|
|
||||||
"16:9",
|
|
||||||
"9:16",
|
|
||||||
"1.85:1",
|
|
||||||
"2.35:1",
|
|
||||||
"2.39:1",
|
|
||||||
"2.40:1",
|
|
||||||
"21:9",
|
|
||||||
"1.375:1",
|
|
||||||
"1.66:1",
|
|
||||||
"1.75:1"
|
|
||||||
]
|
|
||||||
|
|
||||||
cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.enable_insecure_extension_access
|
cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.enable_insecure_extension_access
|
||||||
|
|
||||||
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = \
|
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = \
|
||||||
|
@ -477,9 +459,6 @@ options_templates.update(options_section(('ui', "User interface"), {
|
||||||
"keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
|
"keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
|
||||||
"quicksettings": OptionInfo("sd_model_checkpoint", "Quicksettings list"),
|
"quicksettings": OptionInfo("sd_model_checkpoint", "Quicksettings list"),
|
||||||
"ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
|
"ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
|
||||||
"aspect_ratios_rounding": OptionInfo(True, "Round aspect ratios for more flexibility?", gr.Checkbox),
|
|
||||||
"aspect_ratios_rounding_method": OptionInfo("Ceiling", "Aspect ratios rounding method", gr.Radio,{"choices": ["Round", "Ceiling", "Floor"]}),
|
|
||||||
"aspect_ratios": OptionInfo(", ".join(aspect_ratio_defaults), "txt2img/img2img aspect ratios"),
|
|
||||||
"ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
|
"ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
|
||||||
"localization": OptionInfo("None", "Localization (requires restart)", gr.Dropdown, lambda: {"choices": ["None"] + list(localization.localizations.keys())}, refresh=lambda: localization.list_localizations(cmd_opts.localizations_dir)),
|
"localization": OptionInfo("None", "Localization (requires restart)", gr.Dropdown, lambda: {"choices": ["None"] + list(localization.localizations.keys())}, refresh=lambda: localization.list_localizations(cmd_opts.localizations_dir)),
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -424,10 +424,6 @@ def ordered_ui_categories():
|
||||||
yield category
|
yield category
|
||||||
|
|
||||||
|
|
||||||
def aspect_ratio_list():
|
|
||||||
return [ratio.strip() for ratio in shared.opts.aspect_ratios.split(",")]
|
|
||||||
|
|
||||||
|
|
||||||
def get_value_for_setting(key):
|
def get_value_for_setting(key):
|
||||||
value = getattr(opts, key)
|
value = getattr(opts, key)
|
||||||
|
|
||||||
|
@ -483,8 +479,6 @@ def create_ui():
|
||||||
width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="txt2img_width")
|
width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="txt2img_width")
|
||||||
height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="txt2img_height")
|
height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="txt2img_height")
|
||||||
|
|
||||||
with gr.Column(elem_id="txt2img_size_toolbox", scale=0):
|
|
||||||
aspect_ratio_dropdown = gr.Dropdown(value="🔓", choices=aspect_ratio_list(), interactive=True, type="value", elem_id="txt2img_ratio", show_label=False, label="Aspect Ratio")
|
|
||||||
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn")
|
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn")
|
||||||
if opts.dimensions_and_batch_together:
|
if opts.dimensions_and_batch_together:
|
||||||
with gr.Column(elem_id="txt2img_column_batch"):
|
with gr.Column(elem_id="txt2img_column_batch"):
|
||||||
|
@ -763,8 +757,6 @@ def create_ui():
|
||||||
width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width")
|
width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width")
|
||||||
height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height")
|
height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height")
|
||||||
|
|
||||||
with gr.Column(elem_id="img2img_size_toolbox", scale=0):
|
|
||||||
aspect_ratio_dropdown = gr.Dropdown(value="🔓", choices=aspect_ratio_list(), interactive=True, type="value", elem_id="img2img_ratio", show_label=False, label="Aspect Ratio")
|
|
||||||
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
|
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
|
||||||
if opts.dimensions_and_batch_together:
|
if opts.dimensions_and_batch_together:
|
||||||
with gr.Column(elem_id="img2img_column_batch"):
|
with gr.Column(elem_id="img2img_column_batch"):
|
||||||
|
|
46
style.css
46
style.css
|
@ -747,52 +747,6 @@ footer {
|
||||||
margin-left: 0em;
|
margin-left: 0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#txt2img_size_toolbox, #img2img_size_toolbox{
|
|
||||||
min-width: unset !important;
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#txt2img_ratio, #img2img_ratio {
|
|
||||||
padding: 0px;
|
|
||||||
min-width: unset;
|
|
||||||
max-width: fit-content;
|
|
||||||
}
|
|
||||||
#txt2img_ratio select, #img2img_ratio select{
|
|
||||||
-o-appearance: none;
|
|
||||||
-ms-appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
background-image: unset;
|
|
||||||
padding-right: unset;
|
|
||||||
min-width: 40px;
|
|
||||||
max-width: 40px;
|
|
||||||
min-height: 40px;
|
|
||||||
max-height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.rounding-badge {
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 0px;
|
|
||||||
/*background-color: #ccc;*/
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
top: -10px;
|
|
||||||
right: -10px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
padding: 1px;
|
|
||||||
line-height: 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rounding-badge.active {
|
|
||||||
background-color: #007bff;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inactive{
|
.inactive{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue