directory and file buttons

This commit is contained in:
David Botton 2022-09-13 22:41:10 -04:00
parent 2dbc39481e
commit 09aa23bac8
6 changed files with 230 additions and 123 deletions

View file

@ -2,6 +2,7 @@
(defun populate-dir-win (panel d) (defun populate-dir-win (panel d)
(let ((dir (directory-namestring (uiop:truename* d)))) (let ((dir (directory-namestring (uiop:truename* d))))
(setf (current-dir panel) dir)
;; Dirs ;; Dirs
(setf (inner-html (folders panel)) "") (setf (inner-html (folders panel)) "")
(add-select-option (folders panel) (add-select-option (folders panel)
@ -18,8 +19,56 @@
(defun on-select-dir-win (panel) (defun on-select-dir-win (panel)
(let ((item (value (files panel)))) (let ((item (value (files panel))))
(cond ((and (> (length item) 5) (unless (equal item "")
(equal (subseq item (- (length item) 5)) ".clog")) (cond ((and (> (length item) 5)
(on-new-builder-panel panel :open-file item)) (equal (subseq item (- (length item) 5)) ".clog"))
(t (on-new-builder-panel panel :open-file item))
(on-open-file panel :open-file item))))) (t
(on-open-file panel :open-file item))))))
(defun on-delete-dir-win (panel)
(let ((item (value (files panel))))
(unless (equal item "")
(confirm-dialog panel (format nil "Delete ~A?" item)
(lambda (result)
(when result
(uiop:delete-file-if-exists item)
(populate-dir-win panel (directory-namestring item))))))))
(defun on-new-dir-dir-win (panel)
(input-dialog panel "Name of new directory?"
(lambda (result)
(when result
(ensure-directories-exist (format nil "~A~A/" (current-dir panel) result))
(populate-dir-win panel (current-dir panel))))
:title "New Directory"))
(defun on-delete-dir-dir-win (panel d)
(let ((dir (directory-namestring (uiop:truename* d))))
(confirm-dialog panel (format nil "Delete ~A?" dir)
(lambda (result)
(when result
(handler-case
(uiop:delete-empty-directory dir)
(error ()
(alert-toast panel "Directory Delete Failure"
(format nil "Failed to delete ~A, perhaps not empty." dir))))
(populate-dir-win panel (current-dir panel)))))))
(defun on-rename-dir-dir-win (panel d)
(input-dialog panel "Rename directory to?"
(lambda (result)
(when result
(rename-file d (format nil "~A~A/" (current-dir panel) result))
(populate-dir-win panel (current-dir panel))))
:title "Rename Directory"))
(defun on-rename-dir-win (panel)
(let ((item (value (files panel))))
(unless (equal item "")
(input-dialog panel "Rename file to?"
(lambda (result)
(when result
(rename-file item (format nil "~A~A" (directory-namestring item) result))
(populate-dir-win panel (current-dir panel))))
:title "Rename File"))))

View file

@ -15,11 +15,12 @@
(projects-populate panel))))) (projects-populate panel)))))
(defun projects-view-dir (panel) (defun projects-view-dir (panel)
(ignore-errors (let* ((app (connection-data-item panel "builder-app-data"))
(let* ((app (connection-data-item panel "builder-app-data")) (sel (text-value (project-list panel))))
(sel (text-value (project-list panel))) (if (equal sel "None")
(sys (asdf:find-system (format nil "~A" sel)))) (on-dir-win panel)
(on-dir-win panel :dir (asdf:system-source-directory sys))))) (let ((sys (asdf:find-system (format nil "~A" sel))))
(on-dir-win panel :dir (asdf:system-source-directory sys))))))
(defun projects-run (panel) (defun projects-run (panel)
(let ((val (text-value (entry-point panel)))) (let ((val (text-value (entry-point panel))))

View file

@ -22,7 +22,7 @@
:width 500 :height 250)) :width 500 :height 250))
(prjs (create-project-dir (window-content pwin)))) (prjs (create-project-dir (window-content pwin))))
(window-center pwin) (window-center pwin)
(setf (on-done prjs) (setf (on-done prjs)
(lambda (obj) (lambda (obj)
(declare (ignore obj)) (declare (ignore obj))
(let ((filename (value (project-list prjs)))) (let ((filename (value (project-list prjs))))

View file

@ -1280,19 +1280,19 @@ of controls and double click to select control."
(jquery editor))) (jquery editor)))
(set-on-event-with-data editor "clog-macroexp" (set-on-event-with-data editor "clog-macroexp"
(lambda (obj data) (lambda (obj data)
(let ((p (parse-integer data :junk-allowed t)) (let ((p (parse-integer data :junk-allowed t))
(tv (text-value editor)) (tv (text-value editor))
(lf nil) (lf nil)
(cp 0)) (cp 0))
(loop (loop
(setf (values lf cp) (read-from-string tv nil nil :start cp)) (setf (values lf cp) (read-from-string tv nil nil :start cp))
(unless lf (return nil)) (unless lf (return nil))
(when (> cp p) (return lf))) (when (> cp p) (return lf)))
(let ((result (handler-case (let ((result (handler-case
(prin1-to-string (macroexpand lf)) (prin1-to-string (macroexpand lf))
(error (condition) (error (condition)
(format nil "Error: ~A" condition))))) (format nil "Error: ~A" condition)))))
(on-open-file obj :title-class "w3-blue" :title "macroexpand result" :text result))))) (on-open-file obj :title-class "w3-blue" :title "macroexpand result" :text result)))))
;; expand-region ;; expand-region
(js-execute editor (js-execute editor
(format nil (format nil
@ -1312,23 +1312,23 @@ of controls and double click to select control."
(jquery editor))) (jquery editor)))
(set-on-event-with-data editor "clog-expand-region" (set-on-event-with-data editor "clog-expand-region"
(lambda (obj data) (lambda (obj data)
(declare (ignore obj)) (declare (ignore obj))
(let* ((positions (read-from-string data)) (let* ((positions (read-from-string data))
(new-region (new-region
(judge-expand-region (text-value editor) (judge-expand-region (text-value editor)
(car positions) (car positions)
(cadr positions)))) (cadr positions))))
(js-execute editor (js-execute editor
(format nil (format nil
"var startIndex = ~A; "var startIndex = ~A;
var endIndex = ~A; var endIndex = ~A;
var startRange = ~A.session.doc.indexToPosition(startIndex); var startRange = ~A.session.doc.indexToPosition(startIndex);
var endRange = ~:*~A.session.doc.indexToPosition(endIndex); var endRange = ~:*~A.session.doc.indexToPosition(endIndex);
~:*~A.selection.setRange(new ace.Range(startRange.row, startRange.column, endRange.row, endRange.column));" ~:*~A.selection.setRange(new ace.Range(startRange.row, startRange.column, endRange.row, endRange.column));"
(car new-region) (car new-region)
(cdr new-region) (cdr new-region)
(clog-ace::js-ace editor)))))) (clog-ace::js-ace editor))))))
(set-on-change editor (set-on-change editor
(lambda (obj) (lambda (obj)
(let ((s (js-query obj (format nil (let ((s (js-query obj (format nil
@ -1393,30 +1393,30 @@ var endRange = ~:*~A.session.doc.indexToPosition(endIndex);
It parse the string TEXT without using READ functions." It parse the string TEXT without using READ functions."
(let ((char-count 0) (let ((char-count 0)
(backslash 0) (backslash 0)
exps in-dquotes-p left-dquote left-braces left-brackets) exps in-dquotes-p left-dquote left-braces left-brackets)
(sequence:dosequence (c text) (sequence:dosequence (c text)
(if (= backslash 0) ;current char isn't after a backslash (if (= backslash 0) ;current char isn't after a backslash
(if (eql c #\\) (if (eql c #\\)
(incf backslash) ;if it is a backslash, mark for the next word (incf backslash) ;if it is a backslash, mark for the next word
(if (eql c #\") ;if it is double quote, (if (eql c #\") ;if it is double quote,
(if in-dquotes-p ;end the last string or start a new string (if in-dquotes-p ;end the last string or start a new string
(progn (setf in-dquotes-p nil) (progn (setf in-dquotes-p nil)
(push (cons left-dquote (1+ char-count)) (push (cons left-dquote (1+ char-count))
exps)) exps))
(setf in-dquotes-p t (setf in-dquotes-p t
left-dquote char-count)) left-dquote char-count))
(if (not in-dquotes-p) ;if it isn't double quote, (if (not in-dquotes-p) ;if it isn't double quote,
(case c ;check if it's braces (case c ;check if it's braces
(#\( (push char-count left-braces)) ;mark a new pair (#\( (push char-count left-braces)) ;mark a new pair
(#\) (if left-braces ;end a pair (#\) (if left-braces ;end a pair
(push (cons (pop left-braces) (1+ char-count)) (push (cons (pop left-braces) (1+ char-count))
exps))) exps)))
(#\[ (push char-count left-brackets)) (#\[ (push char-count left-brackets))
(#\] (if left-brackets (#\] (if left-brackets
(push (cons (pop left-brackets) (1+ char-count)) (push (cons (pop left-brackets) (1+ char-count))
exps))))))) exps)))))))
(decf backslash)) (decf backslash))
(incf char-count)) (incf char-count))
exps)) exps))
@ -1424,58 +1424,58 @@ It parse the string TEXT without using READ functions."
"Judge the next wider region to expand to." "Judge the next wider region to expand to."
(declare (string text) (number start) (number end)) (declare (string text) (number start) (number end))
(let ((selected (subseq text start end))) (let ((selected (subseq text start end)))
(or (let ((word-range ;expand to current word (or (let ((word-range ;expand to current word
(ignore-errors (ignore-errors
(let* ((edge-scanner (ppcre:create-scanner "[^\\w]"))) (let* ((edge-scanner (ppcre:create-scanner "[^\\w]")))
(if (not (ppcre:scan edge-scanner selected)) ;there isn't word edge in selected (if (not (ppcre:scan edge-scanner selected)) ;there isn't word edge in selected
(cons (- start ;search for previous word edge (cons (- start ;search for previous word edge
(or (car (ppcre:all-matches (or (car (ppcre:all-matches
edge-scanner edge-scanner
(reverse (subseq text 0 start)))) (reverse (subseq text 0 start))))
start)) ;if nothing, mark from beginning to end. start)) ;if nothing, mark from beginning to end.
(+ end ;search for next word edge (+ end ;search for next word edge
(or (car (ppcre:all-matches edge-scanner (or (car (ppcre:all-matches edge-scanner
(subseq text end))) (subseq text end)))
(- (length text) end))))))))) (- (length text) end)))))))))
(if (not (equal word-range (cons start end))) (if (not (equal word-range (cons start end)))
word-range)) ;return if it isn't same with selected word-range)) ;return if it isn't same with selected
(let ((symbol-range ;expand to current symbol (let ((symbol-range ;expand to current symbol
;; just like expand to word, but search for blanks, braces and double quote. ;; just like expand to word, but search for blanks, braces and double quote.
(ignore-errors (ignore-errors
(let* ((edge-scanner (ppcre:create-scanner "[\\s\\(\\)\\[\\]\"]"))) (let* ((edge-scanner (ppcre:create-scanner "[\\s\\(\\)\\[\\]\"]")))
(if (not (ppcre:scan edge-scanner selected)) (if (not (ppcre:scan edge-scanner selected))
(cons (- start (cons (- start
(or (car (ppcre:all-matches edge-scanner (or (car (ppcre:all-matches edge-scanner
(reverse (subseq text 0 start)))) (reverse (subseq text 0 start))))
start)) start))
(+ end (+ end
(or (car (ppcre:all-matches edge-scanner (or (car (ppcre:all-matches edge-scanner
(subseq text end))) (subseq text end)))
(- (length text) end))))))))) (- (length text) end)))))))))
(if (not (equal symbol-range (cons start end))) (if (not (equal symbol-range (cons start end)))
symbol-range)) symbol-range))
(alexandria:if-let ;expand to curren expression/string (alexandria:if-let ;expand to curren expression/string
((sexp (ignore-errors ((sexp (ignore-errors
(car (sort (delete nil (car (sort (delete nil
(mapcar ;find wider expressions contained selected (mapcar ;find wider expressions contained selected
#'(lambda (pair) #'(lambda (pair)
(if (or (and (< (car pair) start) (if (or (and (< (car pair) start)
(> (cdr pair) end)) (> (cdr pair) end))
(and (= (car pair) start) (and (= (car pair) start)
(> (cdr pair) end)) (> (cdr pair) end))
(and (< (car pair) start) (and (< (car pair) start)
(= (cdr pair) end))) (= (cdr pair) end)))
pair)) pair))
(scan-exps text))) (scan-exps text)))
#'(lambda (obj1 obj2) ;sort it to find the smallest #'(lambda (obj1 obj2) ;sort it to find the smallest
(> (car obj1) (car obj2)))))))) (> (car obj1) (car obj2))))))))
(if (or (= (car sexp) start) ;judge "inner" or "outer" to select (if (or (= (car sexp) start) ;judge "inner" or "outer" to select
(= (cdr sexp) end) (= (cdr sexp) end)
(and (= (1+ (car sexp)) start) (and (= (1+ (car sexp)) start)
(= (1- (cdr sexp)) end))) (= (1- (cdr sexp)) end)))
sexp sexp
(cons (1+ (car sexp)) (1- (cdr sexp)))) (cons (1+ (car sexp)) (1- (cdr sexp))))
(cons start end))))) ;if no expressions, select all (cons start end))))) ;if no expressions, select all
;; Menu handlers ;; Menu handlers

2
tools/dir-view.clog vendored
View file

@ -1 +1 @@
<data id="I3872103154" data-in-package="clog-tools" data-custom-slots="" data-clog-next-id="6" data-clog-title="dir-view"></data><select data-clog-type="listbox" size="4" data-clog-name="folders" style="box-sizing: content-box; position: absolute; left: 10px; top: 10px; right: 10px; height: 150px; overflow: auto;" data-on-create="(populate-dir-win panel &quot;./&quot;)" data-on-change="(populate-dir-win panel (value target))"></select><div data-clog-type="div" data-clog-name="divider" style="box-sizing: content-box; position: absolute; left: 10px; height: 5px; background-attachment: scroll; background-color: rgb(0, 0, 0); right: 10px; top: 166px;"></div><select data-clog-type="listbox" size="4" data-clog-name="files" style="box-sizing: content-box; position: absolute; inset: 175px 10px 10px; overflow: auto;" data-on-double-click="(on-select-dir-win panel)"></select> <data id="I3872110834" data-in-package="clog-tools" data-custom-slots="(current-dir :accessor current-dir :initform &quot;.&quot;)" data-clog-next-id="21" data-clog-title="dir-view"></data><select data-clog-type="listbox" size="4" data-clog-name="folders" style="box-sizing: content-box; position: absolute; left: 10px; top: 10px; right: 10px; height: 115px; overflow: auto;" data-on-create="(populate-dir-win panel &quot;./&quot;)" data-on-mouse-double-click="(populate-dir-win panel (value target))"></select><div data-clog-type="div" data-clog-name="divider" style="box-sizing: content-box; position: absolute; left: 10px; height: 5px; background-attachment: scroll; background-color: rgb(0, 0, 0); right: 10px; top: 166px;"></div><select data-clog-type="listbox" size="4" data-clog-name="files" style="box-sizing: content-box; position: absolute; inset: 175px 10px 40px; overflow: auto;" data-on-double-click="(on-select-dir-win panel)"></select><input type="BUTTON" value="Open" data-clog-type="fbutton" data-clog-name="open-dir-button" style="box-sizing: content-box; position: absolute; left: 10px; top: 132px; width: 70px;" data-on-click="(populate-dir-win panel (value (folders panel)))"><input type="BUTTON" value="New" data-clog-type="fbutton" data-clog-name="new-dir-button" style="box-sizing: content-box; position: absolute; left: 100px; top: 132px; width: 70px;" data-on-click="(on-new-dir-dir-win panel)"><input type="BUTTON" value="Delete" data-clog-type="fbutton" data-clog-name="del-dir-button" style="box-sizing: content-box; position: absolute; left: 190px; top: 132px; width: 70px;" data-on-click="(on-delete-dir-dir-win panel (value (folders panel)))"><input type="BUTTON" value="Rename" data-clog-type="fbutton" data-clog-name="rename-dir-button" style="box-sizing: content-box; position: absolute; left: 280px; top: 132px; width: 70px;" data-on-click="(on-rename-dir-dir-win panel (value (folders panel)))"><input type="BUTTON" value="Open" data-clog-type="fbutton" data-clog-name="open-button" style="box-sizing: content-box; position: absolute; left: 10px; bottom: 5px; width: 70px;" data-on-click="(on-select-dir-win panel)"><input type="BUTTON" value="Delete" data-clog-type="fbutton" data-clog-name="del-button" style="box-sizing: content-box; position: absolute; left: 100px; bottom: 5px; width: 70px;" data-on-click="(on-delete-dir-win panel)"><input type="BUTTON" value="Rename" data-clog-type="fbutton" data-clog-name="rename-button" style="box-sizing: content-box; position: absolute; left: 190px; bottom: 5px; width: 70px;" data-on-click="(on-rename-dir-win panel)">

View file

@ -1,35 +1,92 @@
;;;; CLOG Builder generated code - modify original clog file ;;;; CLOG Builder generated code - modify original clog file
(in-package :clog-tools) (in-package :clog-tools)
(defclass dir-view (clog:clog-panel) (defclass dir-view (clog:clog-panel)
((files :reader files) (divider :reader divider) ((rename-button :reader rename-button)
(folders :reader folders))) (del-button :reader del-button) (open-button :reader open-button)
(rename-dir-button :reader rename-dir-button)
(del-dir-button :reader del-dir-button)
(new-dir-button :reader new-dir-button)
(open-dir-button :reader open-dir-button) (files :reader files)
(divider :reader divider) (folders :reader folders)
(current-dir :accessor current-dir :initform ".")))
(defun create-dir-view (defun create-dir-view
(clog-obj &key (hidden nil) (class nil) (html-id nil) (auto-place t)) (clog-obj &key (hidden nil) (class nil) (html-id nil) (auto-place t))
(let ((panel (let ((panel
(change-class (change-class
(clog:create-div clog-obj :content (clog:create-div clog-obj :content
"<select size=\"4\" style=\"box-sizing: content-box; position: absolute; left: 10px; top: 10px; right: 10px; height: 150px; overflow: auto;\" id=\"CLOGB3872102944\" data-clog-name=\"folders\"></select><div style=\"box-sizing: content-box; position: absolute; left: 10px; height: 5px; background-attachment: scroll; background-color: rgb(0, 0, 0); right: 10px; top: 166px;\" id=\"CLOGB3872102945\" data-clog-name=\"divider\"></div><select size=\"4\" style=\"box-sizing: content-box; position: absolute; inset: 175px 10px 10px; overflow: auto;\" id=\"CLOGB3872102946\" data-clog-name=\"files\"></select>" "<select size=\"4\" style=\"box-sizing: content-box; position: absolute; left: 10px; top: 10px; right: 10px; height: 115px; overflow: auto;\" id=\"CLOGB3872109090\" data-clog-name=\"folders\"></select><div style=\"box-sizing: content-box; position: absolute; left: 10px; height: 5px; background-attachment: scroll; background-color: rgb(0, 0, 0); right: 10px; top: 166px;\" id=\"CLOGB3872109091\" data-clog-name=\"divider\"></div><select size=\"4\" style=\"box-sizing: content-box; position: absolute; inset: 175px 10px 40px; overflow: auto;\" id=\"CLOGB3872109092\" data-clog-name=\"files\"></select><input type=\"BUTTON\" value=\"Open\" style=\"box-sizing: content-box; position: absolute; left: 10px; top: 132px; width: 70px;\" id=\"CLOGB3872109093\" data-clog-name=\"open-dir-button\"><input type=\"BUTTON\" value=\"New\" style=\"box-sizing: content-box; position: absolute; left: 100px; top: 132px; width: 70px;\" id=\"CLOGB3872109094\" data-clog-name=\"new-dir-button\"><input type=\"BUTTON\" value=\"Delete\" style=\"box-sizing: content-box; position: absolute; left: 190px; top: 132px; width: 70px;\" id=\"CLOGB387210909815\" data-clog-name=\"del-dir-button\"><input type=\"BUTTON\" value=\"Rename\" style=\"box-sizing: content-box; position: absolute; left: 280px; top: 132px; width: 70px;\" id=\"CLOGB387211008317\" data-clog-name=\"rename-dir-button\"><input type=\"BUTTON\" value=\"Open\" style=\"box-sizing: content-box; position: absolute; left: 10px; bottom: 5px; width: 70px;\" id=\"CLOGB3872109095\" data-clog-name=\"open-button\"><input type=\"BUTTON\" value=\"Delete\" style=\"box-sizing: content-box; position: absolute; left: 100px; bottom: 5px; width: 70px;\" id=\"CLOGB3872109096\" data-clog-name=\"del-button\"><input type=\"BUTTON\" value=\"Rename\" style=\"box-sizing: content-box; position: absolute; left: 190px; bottom: 5px; width: 70px;\" id=\"CLOGB387211077419\" data-clog-name=\"rename-button\">"
:hidden hidden :class class :html-id html-id :hidden hidden :class class :html-id html-id
:auto-place auto-place) :auto-place auto-place)
'dir-view))) 'dir-view)))
(setf (slot-value panel 'rename-button)
(attach-as-child clog-obj "CLOGB387211077419" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'del-button)
(attach-as-child clog-obj "CLOGB3872109096" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'open-button)
(attach-as-child clog-obj "CLOGB3872109095" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'rename-dir-button)
(attach-as-child clog-obj "CLOGB387211008317" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'del-dir-button)
(attach-as-child clog-obj "CLOGB387210909815" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'new-dir-button)
(attach-as-child clog-obj "CLOGB3872109094" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'open-dir-button)
(attach-as-child clog-obj "CLOGB3872109093" :clog-type
'clog:clog-form-element :new-id t))
(setf (slot-value panel 'files) (setf (slot-value panel 'files)
(attach-as-child clog-obj "CLOGB3872102946" :clog-type (attach-as-child clog-obj "CLOGB3872109092" :clog-type
'clog:clog-select :new-id t)) 'clog:clog-select :new-id t))
(setf (slot-value panel 'divider) (setf (slot-value panel 'divider)
(attach-as-child clog-obj "CLOGB3872102945" :clog-type (attach-as-child clog-obj "CLOGB3872109091" :clog-type
'clog:clog-div :new-id t)) 'clog:clog-div :new-id t))
(setf (slot-value panel 'folders) (setf (slot-value panel 'folders)
(attach-as-child clog-obj "CLOGB3872102944" :clog-type (attach-as-child clog-obj "CLOGB3872109090" :clog-type
'clog:clog-select :new-id t)) 'clog:clog-select :new-id t))
(let ((target (folders panel))) (let ((target (folders panel)))
(declare (ignorable target)) (declare (ignorable target))
(populate-dir-win panel "./")) (populate-dir-win panel "./"))
(clog:set-on-change (folders panel) (clog:set-on-mouse-double-click (folders panel)
(lambda (target) (lambda (target data)
(declare (ignorable target)) (declare (ignorable target data))
(populate-dir-win panel (value target)))) (populate-dir-win panel (value target))))
(clog:set-on-double-click (files panel) (clog:set-on-double-click (files panel)
(lambda (target) (lambda (target)
(declare (ignorable target)) (declare (ignorable target))
(on-select-dir-win panel))) (on-select-dir-win panel)))
(clog:set-on-click (open-dir-button panel)
(lambda (target)
(declare (ignorable target))
(populate-dir-win panel (value (folders panel)))))
(clog:set-on-click (new-dir-button panel)
(lambda (target)
(declare (ignorable target))
(on-new-dir-dir-win panel)))
(clog:set-on-click (del-dir-button panel)
(lambda (target)
(declare (ignorable target))
(on-delete-dir-dir-win panel
(value (folders panel)))))
(clog:set-on-click (rename-dir-button panel)
(lambda (target)
(declare (ignorable target))
(on-rename-dir-dir-win panel
(value (folders panel)))))
(clog:set-on-click (open-button panel)
(lambda (target)
(declare (ignorable target))
(on-select-dir-win panel)))
(clog:set-on-click (del-button panel)
(lambda (target)
(declare (ignorable target))
(on-delete-dir-win panel)))
(clog:set-on-click (rename-button panel)
(lambda (target)
(declare (ignorable target))
(on-rename-dir-win panel)))
panel)) panel))