First GUI Utility command test

I have been working on a command which is aided to create palette when suitable or when requested, in addition to manipulating GUI. This command is named gui_util_pal, it is meant to be used within GUI filters, and this does the work behind the scene. So, I started this thread to see if it works well, and whether there should be new features.

Codewise problem:
_gui_util_pal_set needs to be set via global. Oh well. Not a big deal. Just one of them.

Possible solution involve using BIGINT. I have a few commands that supports numbers much larger than double can store, so I will use this. But really, this makes me want to have BIGINT support within CIMG.h, but you can’t have everything I guess.

Some features I have in mind:

  1. Built-in HSV manipulation. That means to manipulate existing palettes within gui_util_pal.
  2. Using palette to change GUI settings via image. Yes, that means passing a palette image, then gui_util_pal will change the color.

GUI Sample:

#@gui GUI Utility Demo Palette Demo:__none__,fx_rep_gui_toolkit_demo
#@gui:_=note("This filter is to demonstrate the use of the cli command <b>gui_util_pal</b> being in used in GUI filters.")
#@gui:_=separator()
#@gui:1.Display Custom Palette Colors=bool(1)
#@gui:2.Multi-Select Palette Color=bool(0)
#@gui:_=separator()
#@gui:3.Delete All Selected Palette=button(0)
#@gui:4.Number of Color=int(4,2,8)
#@gui:5.Old Number of Color=int(4,2,8)
#@gui:_=separator()
#@gui:6.7.8.Palette Color 1=color(247,244,191)
#@gui:9.‎  ‎  ‎  ‎  Delete Color 1‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:10.Color 1 Selected=_bool(0)
#@gui:11.12.13.Palette Color 2=color(255,240,43)
#@gui:14.‎  ‎  ‎  ‎  Delete Color 2‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:15.Color 2 Selected=_bool(0)
#@gui:16.17.18.Palette Color 3=color(255,207,5)
#@gui:19.‎  ‎  ‎  ‎  Delete Color 3‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:20.Color 3 Selected=_bool(0)
#@gui:21.22.23.Palette Color 4=color(255,177,8)
#@gui:24.‎  ‎  ‎  ‎  Delete Color 4‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:25.23.Color 4 Selected=_bool(0)
#@gui:26.27.28.Palette Color 5=color(233,134,39)
#@gui:29.‎  ‎  ‎  ‎  Delete Color 5‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:30.Color 5 Selected=_bool(0)
#@gui:31.32.33.Palette Color 6=color(191,90,62)
#@gui:34.‎  ‎  ‎  ‎  Delete Color 6‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:35.Color 6 Selected=_bool(0)
#@gui:36.37.38.Palette Color 7=color(156,51,39)
#@gui:39.‎  ‎  ‎  ‎  Delete Color 7‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:40.Color 7 Selected=_bool(0)
#@gui:41.42.43.Palette Color 8=color(114,28,3)
#@gui:44.‎  ‎  ‎  ‎  Delete Color 8‎  ‎  ‎  ‎  ‎  =button(0)
#@gui:45.Color 8 Selected=_bool(0)
#@gui:_=separator()
#@gui:46.‎  ‎  ‎  Add Palette Color‎  ‎ ‎  ‎‎=button(0)
#@gui:47.Palette Color Count Change Effect=choice(0,"Random","Farthest","Rescale")
#@gui:48.Mask Size=float(1,.01,1)
#@gui:49.Cube Size=int(29,14,256)
#@gui:50.Interpolation Method A=choice(2,"None","Nearest","Average","Linear","Grid","Bicubic","Lanczos")
#@gui:51.Interpolation Method B=choice(5,"None","Nearest","Average","Linear","Grid","Bicubic","Lanczos")
#@gui:52.Delete All Selected Palette=button(0)
#@gui:53.Old GUI visible=bool(0)
#@gui:54.Old Selection State=bool(0)
#@gui:55.Old Information=text("")
#@gui:56.Old GUI Setting=text("")
fx_rep_gui_toolkit_demo:
	skip ${55=},${56=}

	## Optional Part - It's up to you to use this ##
	farthest_visible,interpolation_visible=0
	if $47 ${arg\ $47,farthest_visible,interpolation_visible}=2 fi
	## ---------- End of Optional Part ---------- ##

	is_gui_visible=$1
	allow_multiple_selection=$2
	delete_all_selected={$3||$42}
	current_number_of_colors={($4+[0,1])[$46]}
	old_number_of_colors=$5
	method=$47
	method_a,method_b:=[0,0,${48-51}][$method*2,2]
	old_gui_visible=$53
	old_selection_state=$54
	_gui_util_pal_set=$56

	gui_util_pal ,\                            # Your name of palette goes here. Only useful for multiple palette cases
	             3,\                           # Size of Spectrum. Here it is 3
	             $allow_multiple_selection,\   # This alter whether you are able to select multiple colors at once
	             $old_selection_state,\        # This enable swapping of selection states
	             $delete_all_selected,\        # This is a button-related variable to delete checkmarked colors
	             2,8,\                         # 2,8 here are minimum colors possible, and maximum possible color
	             $old_number_of_colors,$current_number_of_colors,\ # This determines whether current number of colors is different from the old numer of colors
	             $method,$method_a,$method_b,\ # How changes in palettes are influenced by changes in palette size
	             $is_gui_visible,\             # Changes in whether palette is visible
	             $old_gui_visible,\            # Changes in visibility of GUI
	             0,\                           # This setting affects whether new palette is always created
	             0,\                           # This setting skips checking GUI. Useful when using multiple palettes or when avoiding checking GUI when irrelevant GUI button is manipulated.
	             "$55",\                       # Insert numerical argument here. This is old_information.
	             ${6-45}                       # Associated with Color and Palette related GUI elements

	# Below set status variable to a string which then changes GUI output
	u "{"$is_gui_visible"}"\
	  "{"$allow_multiple_selection"}"\
	  "{0}"\
	  "{"$_gui_util_pal_color_counts"}"\    # _gui_util_pal_color_counts global variable is created by gui_util_pal. This part is involved in changes of colors which is automatically managed by gui_util_pal
	  "{"$_gui_util_pal_color_counts"}"\    # Yes, a copy is needed so that another run can check the difference
	  $_gui_util_pal_set\                   # _gui_util_pal_set global variable is created by gui_util_pal. This handles everything related to colors and visibility of colors.
	  "{0}"_$_gui_util_pal_enable_add_button\ # This affect whether the to enable a button to add a new color into palette
	  "{$47}"\
	  "{$48}"_$farthest_visible\
	  "{$49}"_$farthest_visible\
	  "{$50}"_$interpolation_visible\
	  "{$51}"_$interpolation_visible\
	  "{0}"\
	  "{"$is_gui_visible"}"\                # Store current Color Selection State
	  "{"$allow_multiple_selection"}"\      # Store current Multiple Selection Option State
	  "{"$_gui_util_pal_old_info"}"\        # _gui_util_pal_old_info is created by gui_util_pal. This stores color information only.
	  "{"$_gui_util_pal_encoded_set"}"      # Store GUI setting. This gets pass-through next iteration.

And the relevant companion command:

#@cli gui_util_pal: name,number_of_channels,selection_state,old_selection_state,delete_selected,minimum_number_of_colors,maximum_number_of_colors,current_number_of_colors,new_number_of_colors,method={ 0=random | 1=farthest (slow) | 2=rescale },method_arg_1,method_arg_2,gui_visible,old_gui_visible,always_generate_new_palette,skip_gui_check,0<=color_0_channel_0<=255,0<=color_0_channel_1<=255,0<=color_0_channel_2<=255,...,delete_color_0={ 0=keep | 1=delete_this }...0<=color_n_channel_c<=255,...,delete_color_n={ 0=keep | 1=delete_this }..
#@cli : Command to be used in GUI filter code in conjunction with specific GUI code. This is not for CLI filters except for debugging!
#@cli :
#@cli : Here's a GUI code example.
#@cli : @--------------------------------------@
#@cli : #@gui:Multi-Select Palette Color=bool(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Delete All Selected Palette=button(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Palette Color 1=color(247,244,191)
#@cli : #@gui:       Delete Color 1          =button(0)
#@cli : #@gui:Color 1 Selected=_bool(0)
#@cli : #@gui:Palette Color 2=color(255,240,43)
#@cli : #@gui:       Delete Color 2          =button(0)
#@cli : #@gui:Color 2 Selected=_bool(0)
#@cli : #@gui:Old Information=text("")
#@cli : @--------------------------------------@
#@cli :
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,3,1,2,1,1,0,0,0,,,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,5,0,1,29,1,0,0,0,"216,255,220,120,160,199,210,222,230",,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
gui_util_pal:
skip "${1=}","${11=}","${12=}","${13=}","${14=}","${17=}","${18=}"

old_status=${}

print_global_vars:=same('$_host','cli') # When debugging via CLI, global variables will be printed!

command_args=number_of_channels,\
             selection_state,\
             old_selection_state,\
             delete,\
             minimum_number_of_colors,\
             maximum_number_of_colors,\
             current_number_of_colors,\
             new_number_of_colors,\
             method,\
             method_arg_1,\
             method_arg_2,\
             gui_visible,\
             old_gui_visible,\
             always_generate_new_palette,\
             skip_gui_check

$command_args=${2-16}

check "isint($number_of_channels,1)
    && isbool($selection_state)
    && isbool($delete)
    && isint($minimum_number_of_colors,1) # && isfinite($minimum_number_of_colors)
    && isint($maximum_number_of_colors,1) # && isfinite($maximum_number_of_colors)
    && isint($current_number_of_colors,1) # && isfinite($current_number_of_colors)
    && isint($current_number_of_colors,$minimum_number_of_colors,$maximum_number_of_colors)
    && isint($method,0,2)
    && narg($gui_visible)"

name=$1
if narg($1)
	name..=_
fi

__gui_util_pal_store_global_vars _$0_set$name

_$0_old_info$name=${__gui_util_pal_decode\ $17}
__gui_util_pal_store_global_vars _$0_old_info$name

_$0_create_new_palette$name=0
__gui_util_pal_store_global_vars _$0_create_new_palette$name

if $method==2
	interpolation_less_than,\
	interpolation_more_than\
	=$method_arg_1,$method_arg_2
else
	mask_factor,\
	cube_size\
	=$method_arg_1,$method_arg_2
fi

if !narg(${_$0_old_info$name})                     # New Palette From Scratch
	_$0_create_new_pal$name=1
	(${18--1})
	group_spectrum_and_delete_info_size:=$number_of_channels+2
	resize. $group_spectrum_and_delete_info_size,{w#-1/$group_spectrum_and_delete_info_size},1,1,-1
	crop. 0,{$number_of_channels-1}
	permute. yzcx
	crop. 0,{$current_number_of_colors-1}
	__gui_util_pal_new_gui_output_from_palette
elif $new_number_of_colors!=$current_number_of_colors # Adjust Palette Size
	_$0_create_new_pal${name}=1
	random,farthest,resize=0,1,2

	__gui_util_pal_create_new_pal_from_old_info
	if $method==$resize
		resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
		round.
		cut. 0,255
		__gui_util_pal_new_gui_output_from_palette
	elif isin($method,$random,$farthest)
		if $new_number_of_colors>$current_number_of_colors
			rep_nonexistent_colors_pal. {$new_number_of_colors-$current_number_of_colors},1,$method,$method_arg_1,$method_arg_2
			rotate. -90
		else
			crop. 0,{$new_number_of_colors-1}
		fi

		m __$0_list_of_checkmark_selection:$""=checkmark
		__$0_list_of_checkmark_selection {[${18--1}][$number_of_channels,$new_number_of_colors,{$number_of_channels+2}]}
		um __$0_list_of_checkmark_selection

		__gui_util_pal_new_gui_output_from_palette_and_preserve_state
	fi
elif $selection_state!=$old_selection_state
	__gui_util_pal_selection_state_switch ${18--1}
elif $skip_gui_check
	skip , # This does nothing. Used to skip the GUI check below
else
	__gui_util_pal_check_gui_change $selection_state,${18--1}
fi

_$0_old_info$name=${__gui_util_pal_encode\ ${_$0_old_info$name}}

_$0_encoded_set$name:='${_$0_set$name}'
__gui_util_pal_store_global_vars _$0_encoded_set$name

_$0_color_counts$name=$new_number_of_colors
__gui_util_pal_store_global_vars _$0_color_counts$name

_$0_enable_add_button$name:=$gui_visible?1+($new_number_of_colors<$maximum_number_of_colors)
__gui_util_pal_store_global_vars _$0_enable_add_button$name

if $print_global_vars
	echo $global_vars
fi

status $old_status
__gui_util_pal_store_global_vars:
if $print_global_vars
	if narg($global_vars)
		global_vars.=\n$1
	else
		global_vars.=$1
	fi
fi
__gui_util_pal_encode:
($*) uint82base64. rm.
__gui_util_pal_decode:
skip "${1=}"
if narg($1) base642uint8 $1 u {crop(#-1)} rm. fi
__gui_util_pal_new_gui_output_from_palette:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]


set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=

sep=
repeat $new_number_of_colors {
	current_color={I[#-1,$>]}
	$old_info.=$sep$current_color
	$set.=\{$current_color\}_$gui_visible
	$set.=\{0\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	sep=,
}

m=$new_number_of_colors
zero_values_color:=vector(#$number_of_channels,0)
for $m<$maximum_number_of_colors {
	$set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0
	m+=1
}
__gui_util_pal_new_gui_output_from_palette_and_preserve_state:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]

set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=

sep=
repeat $new_number_of_colors {
	current_color={I[#-1,$>]}
	$old_info.=$sep$current_color
	$set.=\{$current_color\}_2
	$set.=\{${checkmark{$>+1}}\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	sep=,
}

zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_selection_state_switch:
(${1--1})

visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]

set=_gui_util_pal_set$name
$set=

sep=
step_size:=$number_of_channels+2
limit:=$step_size*$current_number_of_colors
current_pos=0

for $current_pos<$limit {
	current_color={crop(#-1,$current_pos,0,0,0,$number_of_channels,1,1,1)}
	$set.=\{$current_color\}_$visibility_mode
	$set.=\{{i[#-1,$current_pos+$number_of_channels]}\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	current_pos+=$step_size
}

rm.
zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_check_gui_change:
create_new_palette=1
$current_number_of_colors,1,1,$number_of_channels
eval "
	const number_of_channels=$number_of_channels;
	const section_size=number_of_channels+2;
	const current_number_of_colors=$current_number_of_colors;
	const selection_state=$1;

	old_info=["${_gui_util_pal_old_info$name}"];
	current_gui_elements=[${2--1}];

	color_changed=delete_found=new_number_of_colors=0;
	insertion_pos=0;
	for(pos=[0,0,number_of_channels+selection_state],pos[0]<size(old_info),pos+=[number_of_channels,section_size,section_size],
		current_gui_elements[pos[2]]?(
			delete_found=1;
		):(
			current_gui_color=current_gui_elements[pos[1],number_of_channels];
			if(current_gui_color!=old_info[pos[0],number_of_channels],color_changed=1;);
			I[#-1,new_number_of_colors]=current_gui_color;
			++new_number_of_colors;
		);
	);

	gui_changed=color_changed||delete_found;
	set('new_number_of_colors',new_number_of_colors);
	set('gui_changed',gui_changed);
	"

if $new_number_of_colors<$minimum_number_of_colors
	if !$new_number_of_colors
		1,1,1,$number_of_channels,v(0,255)
	fi
	count_of_new_colors:=$minimum_number_of_colors-w#-1
	if $count_of_new_colors>0
		if $method==2&&($count_of_new_colors>1)
			resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
			round.
		elif isin($method,0,1)
			rep_nonexistent_colors_pal. $count_of_new_colors,1,$method,$method_arg_1,$method_arg_2
			rotate. -90
		fi
	fi
	new_number_of_colors=$minimum_number_of_colors
fi

if $gui_changed
	crop. 0,{$new_number_of_colors-1}
elif !$always_generate_new_palette
	create_new_palette=0
fi

__gui_util_pal_new_gui_output_from_palette

if $create_new_palette
	_gui_util_pal_create_new_pal$name=1
else
	rm.
fi
__gui_util_pal_create_new_pal_from_old_info:
(${_gui_util_pal_old_info$name})
resize. $number_of_channels,{w#-1/$number_of_channels},1,1,-1
permute. yzcx

I’m back to this thing. Wow, it been a long time. Anyway, I still have some things to work on. I hope to finish up on GUI sample. Right now, the new code I have allows for using image as argument or import a palette within GUI. For now, you can check the current code things a bit (The CLI examples are invalid).

Code
#@cli gui_util_pal: name,number_of_channels,selection_state,old_selection_state,delete_selected,minimum_number_of_colors,maximum_number_of_colors,current_number_of_colors,new_number_of_colors,method={ 0=random | 1=farthest (slow) | 2=rescale },method_arg_1,method_arg_2,gui_visible,old_gui_visible,always_generate_new_palette,skip_gui_check,0<=color_0_channel_0<=255,0<=color_0_channel_1<=255,0<=color_0_channel_2<=255,...,delete_color_0={ 0=keep | 1=delete_this }...0<=color_n_channel_c<=255,...,delete_color_n={ 0=keep | 1=delete_this }..
#@cli : Command to be used in GUI filter code in conjunction with specific GUI code. This is not for CLI, unless you are debugging.
#@cli :
#@cli : Here's a GUI code example.
#@cli : @--------------------------------------@
#@cli : #@gui:Multi-Select Palette Color=bool(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Delete All Selected Palette=button(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Palette Color 1=color(247,244,191)
#@cli : #@gui:       Delete Color 1          =button(0)
#@cli : #@gui:Color 1 Selected=_bool(0)
#@cli : #@gui:Palette Color 2=color(255,240,43)
#@cli : #@gui:       Delete Color 2          =button(0)
#@cli : #@gui:Color 2 Selected=_bool(0)
#@cli : #@gui:Old Information=text("")
#@cli : @--------------------------------------@
#@cli :
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,3,1,2,1,1,0,0,0,,,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,5,0,1,29,1,0,0,0,"216,255,220,120,160,199,210,222,230",,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
gui_util_pal:
skip "${1=}","${11=}","${12=}","${13=}","${14=}",${15=0},${16=0},"${20=}","${21=}"

old_status=${}

print_global_vars:=same('$_host','cli') # When debugging via CLI, global variables will be printed!

command_args=number_of_channels,\
             selection_state,\
             old_selection_state,\
             delete,\
             minimum_number_of_colors,\
             maximum_number_of_colors,\
             current_number_of_colors,\
             new_number_of_colors,\
             method,\
             method_arg_1,\
             method_arg_2,\
             gui_visible,\
             old_gui_visible,\
             is_file_dialog_active,\
             is_file_imported,\
             main_file_gui_switch_mode,\
             always_generate_new_palette,\
             skip_gui_check

$command_args=${2-19}

check "isint($number_of_channels,1)
    && isbool($selection_state)
    && isbool($delete)
    && isint($minimum_number_of_colors,1) # && isfinite($minimum_number_of_colors)
    && isint($maximum_number_of_colors,1) # && isfinite($maximum_number_of_colors)
    && isint($current_number_of_colors,1) # && isfinite($current_number_of_colors)
    && isint($current_number_of_colors,$minimum_number_of_colors,$maximum_number_of_colors)
    && $minimum_number_of_colors<=$maximum_number_of_colors
    && isint($method,0,2)
    && narg($gui_visible)"

name=$1
if narg($1)
	name..=_
fi

__gui_util_pal_store_global_vars _$0_set$name

_$0_old_info$name=${__gui_util_pal_decode\ $20}
__gui_util_pal_store_global_vars _$0_old_info$name

_$0_create_new_palette$name=0
__gui_util_pal_store_global_vars _$0_create_new_palette$name

if $method==2
	interpolation_less_than,\
	interpolation_more_than\
	=$method_arg_1,$method_arg_2
else
	mask_factor,\
	cube_size\
	=$method_arg_1,$method_arg_2
fi

if !narg(${_$0_old_info$name})                     # New Palette From Scratch
	_$0_create_new_pal$name=1
	(${21--1})
	group_spectrum_and_delete_info_size:=$number_of_channels+2
	resize. $group_spectrum_and_delete_info_size,{w#-1/$group_spectrum_and_delete_info_size},1,1,-1
	crop. 0,{$number_of_channels-1}
	permute. yzcx
	crop. 0,{$current_number_of_colors-1}
	__gui_util_pal_new_gui_output_from_palette
elif $new_number_of_colors!=$current_number_of_colors # Adjust Palette Size
	_$0_create_new_pal${name}=1
	random,farthest,resize=0,1,2

	__gui_util_pal_create_new_pal_from_old_info
	if $method==$resize
		resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
		round.
		cut. 0,255
		__gui_util_pal_new_gui_output_from_palette
	elif isin($method,$random,$farthest)
		if $new_number_of_colors>$current_number_of_colors
			rep_nonexistent_colors_pal. {$new_number_of_colors-$current_number_of_colors},1,$method,$method_arg_1,$method_arg_2
			rotate. -90
		else
			crop. 0,{$new_number_of_colors-1}
		fi

		m __$0_list_of_checkmark_selection:$""=checkmark
		__$0_list_of_checkmark_selection {[${21--1}][$number_of_channels,$new_number_of_colors,{$number_of_channels+2}]}
		um __$0_list_of_checkmark_selection

		__gui_util_pal_new_gui_output_from_palette_and_preserve_state
	fi
elif $selection_state!=$old_selection_state # Change visibility of checkmark/button based on whether to select multiple colors or not
	__gui_util_pal_selection_state_switch ${21--1}
elif ${is_image_arg\ $21} # Used a image source to alter GUI.
	pass$21 0
	__gui_util_pal_new_gui_output_from_palette rm.
elif ${__gui_util_pal_is_valid_file\ ${21--1}} # This is used to import palettes, then use it to alter GUI.
	i ${21--1}
	check s#-1==$number_of_channels&&isint(whd#-1,$minimum_number_of_colors,$maximum_number_of_colors)
	if $main_file_gui_switch_mode gui_visible=0 fi
	__gui_util_pal_new_gui_output_from_palette
	is_file_imported=1
elif $skip_gui_check
	if $always_generate_new_palette
		__gui_util_pal_create_new_pal_from_old_info
	fi
else
	__gui_util_pal_check_gui_change $selection_state,${21--1}
fi

_$0_old_info$name=${__gui_util_pal_encode\ ${_$0_old_info$name}}

_$0_is_file_imported$name=$is_file_imported
__gui_util_pal_store_global_vars _$0_is_file_imported$name

_$0_encoded_set$name:='${_$0_set$name}'
__gui_util_pal_store_global_vars _$0_encoded_set$name

_$0_color_counts$name=$new_number_of_colors
__gui_util_pal_store_global_vars _$0_color_counts$name

_$0_enable_add_button$name:=$gui_visible?1+($new_number_of_colors<$maximum_number_of_colors)
__gui_util_pal_store_global_vars _$0_enable_add_button$name

if $print_global_vars
	echo $global_vars
fi

status $old_status
__gui_util_pal_store_global_vars:
if $print_global_vars
	if narg($global_vars)
		global_vars.=\n$1
	else
		global_vars.=$1
	fi
fi


__gui_util_pal_encode:
($*) uint82base64. rm.
__gui_util_pal_decode:
skip "${1=}"
if narg($1) base642uint8 $1 u {crop(#-1)} rm. fi


__gui_util_pal_new_gui_output_from_palette:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]


set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=

sep=
repeat $new_number_of_colors {
	current_color={I[#-1,$>]}
	$old_info.=$sep$current_color
	$set.=\{$current_color\}_$gui_visible
	$set.=\{0\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	sep=,
}

m=$new_number_of_colors
zero_values_color:=vector(#$number_of_channels,0)
for $m<$maximum_number_of_colors {
	$set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0
	m+=1
}
__gui_util_pal_new_gui_output_from_palette_and_preserve_state:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]

set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=

sep=
repeat $new_number_of_colors {
	current_color={I[#-1,$>]}
	$old_info.=$sep$current_color
	$set.=\{$current_color\}_2
	$set.=\{${checkmark{$>+1}}\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	sep=,
}

zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_selection_state_switch:
(${1--1})

visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]

set=_gui_util_pal_set$name
$set=

sep=
step_size:=$number_of_channels+2
limit:=$step_size*$current_number_of_colors
current_pos=0

for $current_pos<$limit {
	current_color={crop(#-1,$current_pos,0,0,0,$number_of_channels,1,1,1)}
	$set.=\{$current_color\}_$visibility_mode
	$set.=\{{i[#-1,$current_pos+$number_of_channels]}\}_$delete_button_state
	$set.=\{0\}_$select_checkmark
	current_pos+=$step_size
}

rm.
zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_check_gui_change:
create_new_palette=1
$current_number_of_colors,1,1,$number_of_channels
eval "
	const number_of_channels=$number_of_channels;
	const section_size=number_of_channels+2;
	const current_number_of_colors=$current_number_of_colors;
	const selection_state=$1;

	old_info=["${_gui_util_pal_old_info$name}"];
	current_gui_elements=[${2--1}];

	color_changed=delete_found=new_number_of_colors=0;
	insertion_pos=0;
	for(pos=[0,0,number_of_channels+selection_state],pos[0]<size(old_info),pos+=[number_of_channels,section_size,section_size],
		current_gui_elements[pos[2]]?(
			delete_found=1;
		):(
			current_gui_color=current_gui_elements[pos[1],number_of_channels];
			if(current_gui_color!=old_info[pos[0],number_of_channels],color_changed=1;);
			I[#-1,new_number_of_colors]=current_gui_color;
			++new_number_of_colors;
		);
	);

	gui_changed=color_changed||delete_found;
	set('new_number_of_colors',new_number_of_colors);
	set('gui_changed',gui_changed);
	"

if $new_number_of_colors<$minimum_number_of_colors
	if !$new_number_of_colors
		1,1,1,$number_of_channels,v(0,255)
	fi
	count_of_new_colors:=$minimum_number_of_colors-w#-1
	if $count_of_new_colors>0
		if $method==2&&($count_of_new_colors>1)
			resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
			round.
		elif isin($method,0,1)
			rep_nonexistent_colors_pal. $count_of_new_colors,1,$method,$method_arg_1,$method_arg_2
			rotate. -90
		fi
	fi
	new_number_of_colors=$minimum_number_of_colors
fi

if $gui_changed
	crop. 0,{$new_number_of_colors-1}
elif !$always_generate_new_palette
	create_new_palette=0
fi

__gui_util_pal_new_gui_output_from_palette

if $create_new_palette
	_gui_util_pal_create_new_pal$name=1
else
	rm.
fi


__gui_util_pal_create_new_pal_from_old_info:
(${_gui_util_pal_old_info$name})
resize. $number_of_channels,{w#-1/$number_of_channels},1,1,-1
permute. yzcx


__gui_util_pal_is_valid_file:
if ($is_file_dialog_active&&!is_file_imported)?isfile(['"$*"'])
	0 => "$*" ext={-1,x} rm.
	is_valid_ext:=isin('$ext','png','txt','gpl','pal')
	u $is_valid_ext
else
	if !$is_file_dialog_active
		is_file_imported=0
	fi
	u 0
fi

You can see how the code works.