Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Gauthier Quesnel
irritator
Commits
3f4971b6
Commit
3f4971b6
authored
Apr 21, 2020
by
Gauthier Quesnel
Browse files
gui: enable i/o operation
parent
a91f2c26
Pipeline
#11168
failed with stage
in 1 minute and 2 seconds
Changes
5
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
app/gui/CMakeLists.txt
View file @
3f4971b6
...
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
...
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project
(
irritator-gui VERSION 0.1.0 LANGUAGES CXX
)
project
(
irritator-gui VERSION 0.1.0 LANGUAGES CXX
)
set
(
gui_sources
set
(
gui_sources
imnodes.cpp imnodes.hpp window-logger.cpp node-editor.cpp
dialog-file.cpp
imnodes.cpp imnodes.hpp window-logger.cpp node-editor.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.h
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.h
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui_demo.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui_demo.cpp
...
...
app/gui/dialog-file.cpp
0 → 100644
View file @
3f4971b6
// Copyright (c) 2020 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include
"gui.hpp"
#include
<fmt/format.h>
#include
<algorithm>
#include
<array>
#include
<filesystem>
#include
<vector>
#include
<windows.h>
namespace
irt
{
struct
file_dialog
{
std
::
vector
<
std
::
filesystem
::
path
>
paths
;
std
::
filesystem
::
path
current
;
std
::
filesystem
::
path
selected
;
std
::
string
temp
;
char
buffer
[
128
];
bool
is_open
=
true
;
#ifdef _WIN32
uint32_t
drives
{
0
};
void
fill_drives
()
{
DWORD
mask
=
::
GetLogicalDrives
();
uint32_t
ret
=
{
0
};
for
(
int
i
=
0
;
i
<
26
;
++
i
)
{
if
(
!
(
mask
&
(
1
<<
i
)))
continue
;
char
rootName
[
4
]
=
{
static_cast
<
char
>
(
'A'
+
i
),
':'
,
'\\'
,
'\0'
};
UINT
type
=
::
GetDriveTypeA
(
rootName
);
if
(
type
==
DRIVE_REMOVABLE
||
type
==
DRIVE_FIXED
)
ret
|=
(
1
<<
i
);
}
drives
=
ret
;
}
#endif
const
char
**
file_filters
;
const
char
**
extension_filters
;
bool
have_good_file_name_starts
(
const
std
::
filesystem
::
path
&
p
)
{
if
(
file_filters
==
nullptr
)
return
true
;
const
char
**
filters
=
file_filters
;
while
(
*
filters
)
{
if
(
p
.
string
().
starts_with
(
*
filters
))
return
true
;
++
filters
;
}
return
false
;
}
bool
have_good_extension
(
const
std
::
filesystem
::
path
&
p
)
{
if
(
extension_filters
==
nullptr
)
return
true
;
const
char
**
filters
=
extension_filters
;
while
(
*
filters
)
{
if
(
p
.
extension
().
string
()
==
*
filters
)
return
true
;
++
filters
;
}
return
false
;
}
void
copy_files_and_directories
(
const
std
::
filesystem
::
path
&
current_path
)
{
for
(
std
::
filesystem
::
directory_iterator
it
(
current_path
),
et
;
it
!=
et
;
++
it
)
{
std
::
error_code
err
;
if
(
it
->
is_directory
(
err
)
&&
!
err
)
{
paths
.
emplace_back
(
*
it
);
continue
;
}
if
(
it
->
is_regular_file
(
err
)
&&
!
err
)
{
if
(
have_good_extension
(
*
it
)
&&
have_good_file_name_starts
(
*
it
))
{
paths
.
emplace_back
(
*
it
);
continue
;
}
}
}
}
void
sort
()
{
std
::
sort
(
std
::
begin
(
paths
),
std
::
end
(
paths
),
[](
const
auto
&
lhs
,
const
auto
&
rhs
)
{
if
(
std
::
filesystem
::
is_directory
(
lhs
))
{
if
(
std
::
filesystem
::
is_directory
(
rhs
))
return
lhs
.
filename
()
<
rhs
.
filename
();
return
true
;
}
if
(
std
::
filesystem
::
is_directory
(
rhs
))
return
false
;
return
lhs
.
filename
()
<
rhs
.
filename
();
});
}
void
clear
()
{
paths
.
clear
();
selected
.
clear
();
current
.
clear
();
}
void
show_drives
([[
maybe_unused
]]
bool
*
path_click
,
[[
maybe_unused
]]
std
::
filesystem
::
path
*
next
)
{
#ifdef _WIN32
char
current_drive
=
static_cast
<
char
>
(
current
.
c_str
()[
0
]);
char
drive_string
[]
=
{
current_drive
,
':'
,
'\0'
};
ImGui
::
PushItemWidth
(
4
*
ImGui
::
GetFontSize
());
if
(
ImGui
::
BeginCombo
(
"##select_win_drive"
,
drive_string
))
{
for
(
int
i
=
0
;
i
<
26
;
++
i
)
{
if
(
!
(
drives
&
(
1
<<
i
)))
continue
;
char
drive_char
=
static_cast
<
char
>
(
'A'
+
i
);
char
selectable_string
[]
=
{
drive_char
,
':'
,
'\0'
};
bool
is_selected
=
current_drive
==
drive_char
;
if
(
ImGui
::
Selectable
(
selectable_string
,
is_selected
)
&&
!
is_selected
)
{
char
new_current
[]
=
{
drive_char
,
':'
,
'\\'
,
'\0'
};
std
::
error_code
err
;
std
::
filesystem
::
current_path
(
new_current
,
err
);
if
(
!
err
)
{
selected
.
clear
();
*
path_click
=
true
;
*
next
=
std
::
filesystem
::
current_path
(
err
);
}
}
}
ImGui
::
EndCombo
();
}
ImGui
::
PopItemWidth
();
ImGui
::
SameLine
();
#endif
}
void
show_path
(
bool
*
path_click
,
std
::
filesystem
::
path
*
next
)
{
for
(
auto
it
=
current
.
begin
(),
et
=
current
.
end
();
it
!=
et
;
++
it
)
{
if
(
it
!=
current
.
begin
())
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
it
->
string
().
c_str
()))
{
next
->
clear
();
for
(
auto
jt
=
current
.
begin
();
jt
!=
it
;
++
jt
)
*
next
/=
jt
->
native
();
*
next
/=
it
->
native
();
selected
.
clear
();
*
path_click
=
true
;
break
;
}
}
}
};
file_dialog
fd
;
bool
load_file_dialog
(
const
char
*
description
,
const
char
*
filters
[],
std
::
filesystem
::
path
&
out
)
{
if
(
fd
.
current
.
empty
())
{
fd
.
fill_drives
();
fd
.
selected
.
clear
();
std
::
error_code
error
;
fd
.
current
=
std
::
filesystem
::
current_path
(
error
);
}
std
::
filesystem
::
path
next
;
bool
res
=
false
;
if
(
ImGui
::
BeginPopupModal
(
"Select file path to load"
))
{
bool
path_click
=
false
;
fd
.
show_drives
(
&
path_click
,
&
next
);
if
(
!
path_click
)
fd
.
show_path
(
&
path_click
,
&
next
);
if
(
!
path_click
)
{
ImVec2
size
=
ImGui
::
GetContentRegionMax
();
size
.
y
/=
1.5
;
ImGui
::
BeginChild
(
"##select_files"
,
size
);
if
(
ImGui
::
Selectable
(
"..##select_file"
,
(
fd
.
selected
==
".."
)))
{
if
(
next
.
empty
())
{
next
=
fd
.
current
.
parent_path
();
fd
.
selected
.
clear
();
path_click
=
true
;
}
}
for
(
auto
it
=
fd
.
paths
.
begin
(),
et
=
fd
.
paths
.
end
();
it
!=
et
;
++
it
)
{
fd
.
temp
.
clear
();
if
(
std
::
filesystem
::
is_directory
(
*
it
))
fmt
::
format_to
(
std
::
back_inserter
(
fd
.
temp
),
"[Dir] {}"
,
it
->
filename
().
string
());
else
fd
.
temp
=
it
->
filename
().
string
();
if
(
ImGui
::
Selectable
(
fd
.
temp
.
c_str
(),
(
it
->
filename
()
==
fd
.
selected
)))
{
fd
.
selected
=
it
->
filename
();
if
(
std
::
filesystem
::
is_directory
(
*
it
))
{
if
(
next
.
empty
())
{
fd
.
selected
.
clear
();
next
=
fd
.
current
;
next
/=
it
->
filename
();
path_click
=
true
;
}
}
break
;
}
}
ImGui
::
EndChild
();
}
if
(
path_click
)
{
fd
.
paths
.
clear
();
static
const
char
*
filters
[]
=
{
".irt"
,
nullptr
};
fd
.
extension_filters
=
filters
;
fd
.
file_filters
=
nullptr
;
fd
.
copy_files_and_directories
(
next
);
fd
.
sort
();
fd
.
current
=
next
;
}
ImGui
::
Text
(
"File Name: %s"
,
fd
.
selected
.
string
().
c_str
());
float
width
=
ImGui
::
GetContentRegionAvailWidth
();
ImGui
::
PushItemWidth
(
width
);
if
(
ImGui
::
Button
(
"Ok"
,
ImVec2
(
width
/
2
,
0
)))
{
auto
sel
=
fd
.
current
;
sel
/=
fd
.
selected
;
out
=
sel
;
res
=
true
;
}
ImGui
::
SetItemDefaultFocus
();
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"Cancel"
,
ImVec2
(
width
/
2
,
0
)))
{
res
=
true
;
}
ImGui
::
PopItemWidth
();
if
(
res
)
{
ImGui
::
CloseCurrentPopup
();
fd
.
clear
();
}
ImGui
::
EndPopup
();
}
return
res
;
}
bool
save_file_dialog
(
const
char
*
description
,
const
char
*
filters
[],
std
::
filesystem
::
path
&
out
)
{
if
(
fd
.
current
.
empty
())
{
fd
.
fill_drives
();
fd
.
selected
.
clear
();
std
::
error_code
error
;
fd
.
current
=
std
::
filesystem
::
current_path
(
error
);
std
::
strcpy
(
fd
.
buffer
,
"file-name.irt"
);
}
std
::
filesystem
::
path
next
;
bool
res
=
false
;
if
(
ImGui
::
BeginPopupModal
(
"Select file path to save"
))
{
bool
path_click
=
false
;
fd
.
show_drives
(
&
path_click
,
&
next
);
if
(
!
path_click
)
fd
.
show_path
(
&
path_click
,
&
next
);
if
(
!
path_click
)
{
ImVec2
size
=
ImGui
::
GetContentRegionMax
();
size
.
y
/=
1.5
;
ImGui
::
BeginChild
(
"##select_files"
,
size
);
if
(
ImGui
::
Selectable
(
"..##select_file"
,
(
fd
.
selected
==
".."
)))
{
if
(
next
.
empty
())
{
next
=
fd
.
current
.
parent_path
();
fd
.
selected
.
clear
();
path_click
=
true
;
}
}
for
(
auto
it
=
fd
.
paths
.
begin
(),
et
=
fd
.
paths
.
end
();
it
!=
et
;
++
it
)
{
fd
.
temp
.
clear
();
if
(
std
::
filesystem
::
is_directory
(
*
it
))
fmt
::
format_to
(
std
::
back_inserter
(
fd
.
temp
),
"[Dir] {}"
,
it
->
filename
().
string
());
else
fd
.
temp
=
it
->
filename
().
string
();
if
(
ImGui
::
Selectable
(
fd
.
temp
.
c_str
(),
(
it
->
filename
()
==
fd
.
selected
)))
{
fd
.
selected
=
it
->
filename
();
if
(
std
::
filesystem
::
is_directory
(
*
it
))
{
if
(
next
.
empty
())
{
fd
.
selected
.
clear
();
next
=
fd
.
current
;
next
/=
it
->
filename
();
path_click
=
true
;
}
}
if
(
std
::
filesystem
::
is_regular_file
(
*
it
))
{
strncpy
(
fd
.
buffer
,
it
->
filename
().
string
().
c_str
(),
IM_ARRAYSIZE
(
fd
.
buffer
));
}
break
;
}
}
ImGui
::
EndChild
();
}
if
(
path_click
)
{
fd
.
paths
.
clear
();
static
const
char
*
filters
[]
=
{
".irt"
,
nullptr
};
fd
.
extension_filters
=
filters
;
fd
.
file_filters
=
nullptr
;
fd
.
copy_files_and_directories
(
next
);
fd
.
sort
();
fd
.
current
=
next
;
}
ImGui
::
InputText
(
"File Name"
,
fd
.
buffer
,
IM_ARRAYSIZE
(
fd
.
buffer
));
ImGui
::
Text
(
"Directory name: %s"
,
fd
.
current
.
string
().
c_str
());
float
width
=
ImGui
::
GetContentRegionAvailWidth
();
ImGui
::
PushItemWidth
(
width
);
if
(
ImGui
::
Button
(
"Ok"
,
ImVec2
(
width
/
2
,
0
)))
{
auto
sel
=
fd
.
current
;
sel
/=
fd
.
buffer
;
out
=
sel
;
res
=
true
;
}
ImGui
::
SetItemDefaultFocus
();
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"Cancel"
,
ImVec2
(
width
/
2
,
0
)))
{
res
=
true
;
}
ImGui
::
PopItemWidth
();
if
(
res
)
{
ImGui
::
CloseCurrentPopup
();
fd
.
clear
();
}
ImGui
::
EndPopup
();
}
return
res
;
}
}
// namespace irt
\ No newline at end of file
app/gui/gui.hpp
View file @
3f4971b6
...
@@ -7,6 +7,9 @@
...
@@ -7,6 +7,9 @@
#include
<imgui.h>
#include
<imgui.h>
#include
<filesystem>
#include
<string>
namespace
irt
{
namespace
irt
{
void
void
...
@@ -34,6 +37,18 @@ struct window_logger
...
@@ -34,6 +37,18 @@ struct window_logger
void
show
(
bool
*
is_show
);
void
show
(
bool
*
is_show
);
};
};
/* Filesytem dialog box */
bool
load_file_dialog
(
const
char
*
description
,
const
char
*
filters
[],
std
::
filesystem
::
path
&
out
);
bool
save_file_dialog
(
const
char
*
description
,
const
char
*
filters
[],
std
::
filesystem
::
path
&
out
);
}
// namespace irt
}
// namespace irt
#endif
#endif
app/gui/node-editor.cpp
View file @
3f4971b6
...
@@ -2,18 +2,18 @@
...
@@ -2,18 +2,18 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// http://www.boost.org/LICENSE_1_0.txt)
#include
"gui.hpp"
#include
"imnodes.hpp"
#include
<filesystem>
#include
<future>
#include
<future>
#include
<mutex>
#include
<mutex>
#include
<string>
#include
<thread>
#include
<thread>
#include
"imgui.h"
#include
"imnodes.hpp"
#include
"gui.hpp"
#include
<fmt/format.h>
#include
<fmt/format.h>
#include
<irritator/core.hpp>
#include
<irritator/core.hpp>
#include
<irritator/io.hpp>
namespace
irt
{
namespace
irt
{
...
@@ -90,14 +90,14 @@ run_simulation(simulation& sim,
...
@@ -90,14 +90,14 @@ run_simulation(simulation& sim,
current
=
begin
;
current
=
begin
;
if
(
auto
ret
=
sim
.
initialize
(
current
);
irt
::
is_bad
(
ret
))
{
if
(
auto
ret
=
sim
.
initialize
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
log_w
.
log
(
3
,
"Simulation initialization failure (%d)"
,
static_cast
<
int
>
(
ret
));
3
,
"Simulation initialization failure (%d)
\n
"
,
static_cast
<
int
>
(
ret
));
st
=
simulation_status
::
internal_error
;
st
=
simulation_status
::
internal_error
;
return
;
return
;
}
}
do
{
do
{
if
(
auto
ret
=
sim
.
run
(
current
);
irt
::
is_bad
(
ret
))
{
if
(
auto
ret
=
sim
.
run
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation run failure (%d)"
,
static_cast
<
int
>
(
ret
));
log_w
.
log
(
3
,
"Simulation run failure (%d)
\n
"
,
static_cast
<
int
>
(
ret
));
st
=
simulation_status
::
internal_error
;
st
=
simulation_status
::
internal_error
;
return
;
return
;
}
}
...
@@ -111,10 +111,20 @@ run_simulation(simulation& sim,
...
@@ -111,10 +111,20 @@ run_simulation(simulation& sim,
struct
editor
struct
editor
{
{
small_string
<
16
>
name
;
small_string
<
16
>
name
;
std
::
filesystem
::
path
path
;
imnodes
::
EditorContext
*
context
=
nullptr
;
imnodes
::
EditorContext
*
context
=
nullptr
;
bool
initialized
=
false
;
bool
initialized
=
false
;
bool
show
=
true
;
bool
show
=
true
;
simulation
sim
;
double
simulation_begin
=
0.0
;
double
simulation_end
=
10.0
;
double
simulation_current
=
10.0
;
std
::
future
<
std
::
tuple
<
std
::
string
,
status
>>
future_content
;
std
::
thread
simulation_thread
;
simulation_status
st
=
simulation_status
::
uninitialized
;
bool
stop
=
false
;
vector
<
observation_output
>
observation_outputs
;
vector
<
observation_output
>
observation_outputs
;
void
clear
()
void
clear
()
...
@@ -172,15 +182,6 @@ struct editor
...
@@ -172,15 +182,6 @@ struct editor
return
sim
.
output_ports
.
get_id
(
port
);
return
sim
.
output_ports
.
get_id
(
port
);
}
}
simulation
sim
;
double
simulation_begin
=
0.0
;
double
simulation_end
=
10.0
;
double
simulation_current
=
10.0
;
std
::
future
<
std
::
tuple
<
std
::
string
,
status
>>
future_content
;
std
::
thread
simulation_thread
;
simulation_status
st
=
simulation_status
::
uninitialized
;
bool
stop
=
false
;
status
initialize
(
u32
id
)
noexcept
status
initialize
(
u32
id
)
noexcept
{
{
if
(
is_bad
(
sim
.
init
(
1024u
,
32768u
))
||
if
(
is_bad
(
sim
.
init
(
1024u
,
32768u
))
||
...
@@ -707,6 +708,8 @@ struct editor
...
@@ -707,6 +708,8 @@ struct editor
bool
show_editor
()
bool
show_editor
()
{
{
imnodes
::
EditorContextSet
(
context
);
imnodes
::
EditorContextSet
(
context
);
static
bool
show_load_file_dialog
=
false
;
static
bool
show_save_file_dialog
=
false
;
ImGuiWindowFlags
windows_flags
=
0
;
ImGuiWindowFlags
windows_flags
=
0
;
windows_flags
|=
ImGuiWindowFlags_MenuBar
;
windows_flags
|=
ImGuiWindowFlags_MenuBar
;
...
@@ -718,9 +721,21 @@ struct editor
...
@@ -718,9 +721,21 @@ struct editor
if
(
ImGui
::
BeginMenuBar
())
{
if
(
ImGui
::
BeginMenuBar
())
{
if
(
ImGui
::
BeginMenu
(
"File"
))
{
if
(
ImGui
::
BeginMenu
(
"File"
))
{
ImGui
::
MenuItem
(
"Open"
);
if
(
ImGui
::
MenuItem
(
"Open"
))
ImGui
::
MenuItem
(
"Save"
);
show_load_file_dialog
=
true
;
ImGui
::
MenuItem
(
"Save as..."
);
if
(
!
path
.
empty
()
&&
ImGui
::
MenuItem
(
"Save"
))
{
log_w
.
log
(
3
,
"Write into file %s
\n
"
,
path
.
string
().
c_str
());
writer
w
(
std
::
fopen
(
path
.
string
().
c_str
(),
"w"
));
auto
ret
=
w
(
sim
);
if
(
is_success
(
ret
))
log_w
.
log
(
5
,
"success
\n
"
);
else
log_w
.
log
(
4
,
"error writing
\n
"
);
}
if
(
ImGui
::
MenuItem
(
"Save as..."
))
show_save_file_dialog
=
true
;
if
(
ImGui
::
MenuItem
(
"Close"
))
{
if
(
ImGui
::
MenuItem
(
"Close"
))
{
ImGui
::
EndMenu
();
ImGui
::
EndMenu
();
...
@@ -741,12 +756,12 @@ struct editor
...
@@ -741,12 +756,12 @@ struct editor
if
(
ImGui
::
BeginMenu
(
"Examples"
))
{
if
(
ImGui
::
BeginMenu