Release with changes to OneLineProgressMeter
This commit is contained in:
parent
03d9c2dde4
commit
35ca4a3756
132
PySimpleGUI27.py
132
PySimpleGUI27.py
|
@ -6,6 +6,7 @@ from __future__ import absolute_import
|
||||||
from builtins import super
|
from builtins import super
|
||||||
from builtins import open
|
from builtins import open
|
||||||
from builtins import range
|
from builtins import range
|
||||||
|
from builtins import map
|
||||||
from builtins import int
|
from builtins import int
|
||||||
from builtins import str
|
from builtins import str
|
||||||
from builtins import object
|
from builtins import object
|
||||||
|
@ -35,6 +36,18 @@ import pickle
|
||||||
import calendar
|
import calendar
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 888888ba .d88888b oo dP .88888. dP dP dP
|
||||||
|
# 88 `8b 88. "' 88 d8' `88 88 88 88
|
||||||
|
# a88aaaa8P' dP dP `Y88888b. dP 88d8b.d8b. 88d888b. 88 .d8888b. 88 88 88 88
|
||||||
|
# 88 88 88 `8b 88 88'`88'`88 88' `88 88 88ooood8 88 YP88 88 88 88
|
||||||
|
# 88 88. .88 d8' .8P 88 88 88 88 88. .88 88 88. ... Y8. .88 Y8. .8P 88
|
||||||
|
# dP `8888P88 Y88888P dP dP dP dP 88Y888P' dP `88888P' `88888' `Y88888P' dP
|
||||||
|
# .88 88
|
||||||
|
# d8888P dP
|
||||||
|
|
||||||
|
|
||||||
g_time_start = 0
|
g_time_start = 0
|
||||||
g_time_end = 0
|
g_time_end = 0
|
||||||
g_time_delta = 0
|
g_time_delta = 0
|
||||||
|
@ -1173,7 +1186,7 @@ class Text(Element):
|
||||||
:param tooltip:
|
:param tooltip:
|
||||||
:param visible:
|
:param visible:
|
||||||
'''
|
'''
|
||||||
self.DisplayText = text
|
self.DisplayText = str(text)
|
||||||
self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
|
self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
|
||||||
self.Justification = justification
|
self.Justification = justification
|
||||||
self.Relief = relief
|
self.Relief = relief
|
||||||
|
@ -1926,7 +1939,10 @@ class Image(Element):
|
||||||
else:
|
else:
|
||||||
self.CurrentFrameNumber = self.CurrentFrameNumber + 1 if self.CurrentFrameNumber+1< self.TotalAnimatedFrames else 0
|
self.CurrentFrameNumber = self.CurrentFrameNumber + 1 if self.CurrentFrameNumber+1< self.TotalAnimatedFrames else 0
|
||||||
image = self.AnimatedFrames[self.CurrentFrameNumber]
|
image = self.AnimatedFrames[self.CurrentFrameNumber]
|
||||||
self.tktext_label.configure(image=image, width=image.width(), heigh=image.height())
|
try: # needed in case the window was closed with an "X"
|
||||||
|
self.tktext_label.configure(image=image, width=image.width(), heigh=image.height())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2036,7 +2052,12 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
|
try: # in case window was closed with an X
|
||||||
|
id = self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
|
|
||||||
def DrawPoint(self, point, size=2, color='black'):
|
def DrawPoint(self, point, size=2, color='black'):
|
||||||
if point == (None, None):
|
if point == (None, None):
|
||||||
|
@ -2046,9 +2067,14 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size,
|
try: # needed in case window was closed with an X
|
||||||
|
id = self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size,
|
||||||
converted_point[0] + size, converted_point[1] + size, fill=color,
|
converted_point[0] + size, converted_point[1] + size, fill=color,
|
||||||
outline=color)
|
outline=color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'):
|
def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'):
|
||||||
if center_location == (None, None):
|
if center_location == (None, None):
|
||||||
|
@ -2058,9 +2084,13 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_oval(converted_point[0] - radius, converted_point[1] - radius,
|
try: # needed in case the window was closed with an X
|
||||||
|
id = self._TKCanvas2.create_oval(converted_point[0] - radius, converted_point[1] - radius,
|
||||||
converted_point[0] + radius, converted_point[1] + radius, fill=fill_color,
|
converted_point[0] + radius, converted_point[1] + radius, fill=fill_color,
|
||||||
outline=line_color)
|
outline=line_color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None):
|
def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None):
|
||||||
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
||||||
|
@ -2069,8 +2099,13 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
try: # in case windows close with X
|
||||||
|
id = self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
||||||
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
|
||||||
|
return id
|
||||||
|
|
||||||
def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'):
|
def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'):
|
||||||
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
||||||
|
@ -2080,9 +2115,13 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
try: # in case closed with X
|
||||||
|
id = self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
||||||
converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle,
|
converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle,
|
||||||
outline=arc_color)
|
outline=arc_color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None):
|
def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None):
|
||||||
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
|
||||||
|
@ -2091,8 +2130,13 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
return self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
try: # in case closed with X
|
||||||
|
id = self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
|
||||||
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
|
|
||||||
def DrawText(self, text, location, color='black', font=None, angle=0):
|
def DrawText(self, text, location, color='black', font=None, angle=0):
|
||||||
if location == (None, None):
|
if location == (None, None):
|
||||||
|
@ -2102,9 +2146,12 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
text_id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color,
|
try: # in case closed with X
|
||||||
|
id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color,
|
||||||
angle=angle)
|
angle=angle)
|
||||||
return text_id
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
|
|
||||||
def DrawImage(self, filename=None, data=None, location=(None, None), color='black', font=None, angle=0):
|
def DrawImage(self, filename=None, data=None, location=(None, None), color='black', font=None, angle=0):
|
||||||
|
@ -2124,8 +2171,11 @@ class Graph(Element):
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
self.Images.append(image)
|
self.Images.append(image)
|
||||||
text_id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW)
|
try: # in case closed with X
|
||||||
return text_id
|
id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW)
|
||||||
|
except:
|
||||||
|
id = None
|
||||||
|
return id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2134,7 +2184,10 @@ class Graph(Element):
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
print('Call Window.Finalize() prior to this operation')
|
print('Call Window.Finalize() prior to this operation')
|
||||||
return None
|
return None
|
||||||
self._TKCanvas2.delete('all')
|
try: # in case window was closed with X
|
||||||
|
self._TKCanvas2.delete('all')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def DeleteFigure(self, id):
|
def DeleteFigure(self, id):
|
||||||
|
@ -4719,11 +4772,17 @@ else:
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# 888 888 d8b 888
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# 888 888 Y8P 888
|
||||||
# ===================================== TK CODE STARTS HERE ====================================================== #
|
# 888 888 888
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# 888888 888 888 888 88888b. 888888 .d88b. 888d888
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# 888 888 .88P 888 888 "88b 888 d8P Y8b 888P"
|
||||||
|
# 888 888888K 888 888 888 888 88888888 888
|
||||||
|
# Y88b. 888 "88b 888 888 888 Y88b. Y8b. 888
|
||||||
|
# "Y888 888 888 888 888 888 "Y888 "Y8888 888
|
||||||
|
|
||||||
|
|
||||||
|
# ======================== TK CODE STARTS HERE ========================================= #
|
||||||
|
|
||||||
def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
def CharWidthInPixels():
|
def CharWidthInPixels():
|
||||||
|
@ -4846,6 +4905,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# ------------------------- TEXT element ------------------------- #
|
# ------------------------- TEXT element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_TEXT:
|
elif element_type == ELEM_TYPE_TEXT:
|
||||||
# auto_size_text = element.AutoSizeText
|
# auto_size_text = element.AutoSizeText
|
||||||
|
element = element # type: Text
|
||||||
display_text = element.DisplayText # text to display
|
display_text = element.DisplayText # text to display
|
||||||
if auto_size_text is False:
|
if auto_size_text is False:
|
||||||
width, height = element_size
|
width, height = element_size
|
||||||
|
@ -5197,7 +5257,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
listbox_frame = tk.Frame(tk_row_frame)
|
listbox_frame = tk.Frame(tk_row_frame)
|
||||||
element.TKStringVar = tk.StringVar()
|
element.TKStringVar = tk.StringVar()
|
||||||
element.TKListbox = tk.Listbox(listbox_frame, height=element_size[1], width=width,
|
element.TKListbox = tk.Listbox(listbox_frame, height=element_size[1], width=width,
|
||||||
selectmode=element.SelectMode, font=font)
|
selectmode=element.SelectMode, font=font, exportselection=False)
|
||||||
for index, item in enumerate(element.Values):
|
for index, item in enumerate(element.Values):
|
||||||
element.TKListbox.insert(tk.END, item)
|
element.TKListbox.insert(tk.END, item)
|
||||||
if element.DefaultValues is not None and item in element.DefaultValues:
|
if element.DefaultValues is not None and item in element.DefaultValues:
|
||||||
|
@ -5229,8 +5289,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
AddMenuItem(top_menu, menu[1], element)
|
AddMenuItem(top_menu, menu[1], element)
|
||||||
element.TKRightClickMenu = top_menu
|
element.TKRightClickMenu = top_menu
|
||||||
element.TKListbox.bind('<Button-3>', element.RightClickMenuCallback)
|
element.TKListbox.bind('<Button-3>', element.RightClickMenuCallback)
|
||||||
# ------------------------- INPUT MULTI LINE element ------------------------- #
|
# ------------------------- MULTILINE element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_MULTILINE:
|
elif element_type == ELEM_TYPE_INPUT_MULTILINE:
|
||||||
|
element = element # type: Multiline
|
||||||
default_text = element.DefaultText
|
default_text = element.DefaultText
|
||||||
width, height = element_size
|
width, height = element_size
|
||||||
element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word',
|
element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word',
|
||||||
|
@ -6112,7 +6173,7 @@ class QuickMeter(object):
|
||||||
layout = []
|
layout = []
|
||||||
if self.orientation.lower().startswith('h'):
|
if self.orientation.lower().startswith('h'):
|
||||||
col = []
|
col = []
|
||||||
col += [[T(arg)] for arg in args]
|
col += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated
|
||||||
col += [[T('', size=(30,10), key='_STATS_')],
|
col += [[T('', size=(30,10), key='_STATS_')],
|
||||||
[ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, bar_color=self.bar_color)],
|
[ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, bar_color=self.bar_color)],
|
||||||
[Cancel(button_color=self.button_color), Stretch()]]
|
[Cancel(button_color=self.button_color), Stretch()]]
|
||||||
|
@ -6120,7 +6181,7 @@ class QuickMeter(object):
|
||||||
else:
|
else:
|
||||||
col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, bar_color=self.bar_color)]]
|
col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, bar_color=self.bar_color)]]
|
||||||
col2 = []
|
col2 = []
|
||||||
col2 += [[T(arg)] for arg in args]
|
col2 += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated
|
||||||
col2 += [[T('', size=(30,10), key='_STATS_')],
|
col2 += [[T('', size=(30,10), key='_STATS_')],
|
||||||
[Cancel(button_color=self.button_color), Stretch()]]
|
[Cancel(button_color=self.button_color), Stretch()]]
|
||||||
layout = [Column(col), Column(col2)]
|
layout = [Column(col), Column(col2)]
|
||||||
|
@ -6129,11 +6190,12 @@ class QuickMeter(object):
|
||||||
|
|
||||||
return self.window
|
return self.window
|
||||||
|
|
||||||
def UpdateMeter(self, current_value, max_value):
|
def UpdateMeter(self, current_value, max_value,*args): ### support for *args when updating
|
||||||
self.current_value = current_value
|
self.current_value = current_value
|
||||||
self.max_value = max_value
|
self.max_value = max_value
|
||||||
self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value)
|
self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value)
|
||||||
self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats()))
|
self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats()))
|
||||||
|
self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args
|
||||||
event, values = self.window.Read(timeout=0)
|
event, values = self.window.Read(timeout=0)
|
||||||
if event in('Cancel', None) or current_value >= max_value:
|
if event in('Cancel', None) or current_value >= max_value:
|
||||||
self.window.Close()
|
self.window.Close()
|
||||||
|
@ -6192,10 +6254,11 @@ def OneLineProgressMeter(title, current_value, max_value, key, *args, **_3to2kwa
|
||||||
else:
|
else:
|
||||||
meter = QuickMeter.active_meters[key]
|
meter = QuickMeter.active_meters[key]
|
||||||
|
|
||||||
rc = meter.UpdateMeter(current_value, max_value)
|
rc = meter.UpdateMeter(current_value, max_value,*args) ### pass the *args to to UpdateMeter function
|
||||||
OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons)
|
OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons)
|
||||||
return rc == METER_OK
|
return rc == METER_OK
|
||||||
|
|
||||||
|
|
||||||
def OneLineProgressMeterCancel(key):
|
def OneLineProgressMeterCancel(key):
|
||||||
try:
|
try:
|
||||||
meter = QuickMeter.active_meters[key]
|
meter = QuickMeter.active_meters[key]
|
||||||
|
@ -6896,11 +6959,18 @@ def ObjToString(obj, extra=' '):
|
||||||
for item in sorted(obj.__dict__)))
|
for item in sorted(obj.__dict__)))
|
||||||
|
|
||||||
|
|
||||||
|
######
|
||||||
|
# # #### ##### # # ##### ####
|
||||||
|
# # # # # # # # # # #
|
||||||
|
###### # # # # # # # # ####
|
||||||
|
# # # ##### # # ##### #
|
||||||
|
# # # # # # # # #
|
||||||
|
# #### # #### # ####
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# ------------------------------------------------------------------------------------------------------------------ #
|
||||||
# ===================================== Upper PySimpleGUI ======================================================== #
|
# ===================================== Upper PySimpleGUI ======================================================== #
|
||||||
# Pre-built dialog boxes for all your needs These are the "high level API calls #
|
|
||||||
# ------------------------------------------------------------------------------------------------------------------ #
|
# ------------------------------------------------------------------------------------------------------------------ #
|
||||||
|
|
||||||
# ----------------------------------- The mighty Popup! ------------------------------------------------------------ #
|
# ----------------------------------- The mighty Popup! ------------------------------------------------------------ #
|
||||||
|
|
||||||
def Popup(*args, **_3to2kwargs):
|
def Popup(*args, **_3to2kwargs):
|
||||||
|
@ -7849,7 +7919,17 @@ def PopupAnimated(image_source, message=None, background_color=None, text_color=
|
||||||
|
|
||||||
window.Refresh() # call refresh instead of Read to save significant CPU time
|
window.Refresh() # call refresh instead of Read to save significant CPU time
|
||||||
|
|
||||||
|
"""
|
||||||
|
d8b
|
||||||
|
Y8P
|
||||||
|
|
||||||
|
88888b.d88b. 8888b. 888 88888b.
|
||||||
|
888 "888 "88b "88b 888 888 "88b
|
||||||
|
888 888 888 .d888888 888 888 888
|
||||||
|
888 888 888 888 888 888 888 888
|
||||||
|
888 888 888 "Y888888 888 888 888
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
Loading…
Reference in New Issue