Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
d08cd3626d | |||
ef180f3ea2 | |||
74ecde9807 | |||
cd2cf8c5c7 | |||
63eb65a3c4 | |||
aa413732f1 | |||
54165a8475 | |||
c3c4636334 | |||
f4de9c4402 | |||
a016a18587 | |||
a3626e7b33 | |||
4dcafeed3f | |||
03e2b15571 | |||
e278ad6d94 | |||
8d8af8d211 | |||
4bed016f01 | |||
e8c7f78af4 | |||
60e20f45cc | |||
cd55137951 | |||
d6fb6ba6b0 | |||
829c9a2386 | |||
a99a469cf0 | |||
f237004e6c | |||
188086de52 | |||
38f18009fc | |||
ff3f692f2c | |||
5537c076a8 | |||
b43b142a75 | |||
4c0df56386 | |||
008fe52cb2 | |||
67f9d9b4ee | |||
e289e7b301 | |||
b9cc8570ac | |||
5357aff1b8 | |||
64508104bc | |||
60f54e2240 | |||
19b26a3c26 | |||
28734a797a | |||
31d9d26aa4 | |||
45f0d90a87 | |||
587b79dc31 | |||
67e5023c1e | |||
c94c3d591e | |||
c9e2c2a76d | |||
bb2a4f7f04 | |||
6b03695824 |
@@ -10,27 +10,27 @@ add_subdirectory(glade)
|
|||||||
add_subdirectory(doxygen)
|
add_subdirectory(doxygen)
|
||||||
add_subdirectory(version)
|
add_subdirectory(version)
|
||||||
|
|
||||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
|
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||||
|
|
||||||
aux_source_directory("widgets" LAYER_SOURCES)
|
aux_source_directory("widgets" LAYER_SOURCES)
|
||||||
aux_source_directory("tree-renderer" RENDERER_SOURCES)
|
aux_source_directory("tree-renderer" RENDERER_SOURCES)
|
||||||
aux_source_directory("gds-parser" PARSER_SOURCES)
|
aux_source_directory("gds-utils" GDS_SOURCES)
|
||||||
aux_source_directory("latex-output" LATEX_SOURCES)
|
aux_source_directory("latex-renderer" LATEX_SOURCES)
|
||||||
aux_source_directory("cairo-output" CAIRO_SOURCES)
|
aux_source_directory("cairo-renderer" CAIRO_SOURCES)
|
||||||
aux_source_directory("trigonometric" TRIG_SOURCES)
|
aux_source_directory("geometric" GEOMETRIC_SOURCES)
|
||||||
aux_source_directory("layer-selector" LAYER_SELECTOR_SOURCES)
|
aux_source_directory("layer" LAYER_SELECTOR_SOURCES)
|
||||||
set(SOURCE "main.c" "mapping-parser.c" "command-line.c" "main-window.c" "external-renderer.c")
|
set(SOURCE "main.c" "command-line.c" "gds-render-gui.c" "external-renderer.c")
|
||||||
|
|
||||||
set(SOURCE
|
set(SOURCE
|
||||||
${SOURCE}
|
${SOURCE}
|
||||||
${LAYER_SOURCES}
|
${LAYER_SOURCES}
|
||||||
${RENDERER_SOURCES}
|
${RENDERER_SOURCES}
|
||||||
${PARSER_SOURCES}
|
${GDS_SOURCES}
|
||||||
${LATEX_SOURCES}
|
${LATEX_SOURCES}
|
||||||
${CAIRO_SOURCES}
|
${CAIRO_SOURCES}
|
||||||
${TRIG_SOURCES}
|
${GEOMETRIC_SOURCES}
|
||||||
${LAYER_SELECTOR_SOURCES}
|
${LAYER_SELECTOR_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# GDS-Render
|
# GDS-Render Readme
|
||||||
|
|
||||||
This software is a rendering programm for GDS2 layout files.
|
This software is a rendering programm for GDS2 layout files.
|
||||||
The GDS2 format is mainly used in integrated circuit development.
|
The GDS2 format is mainly used in integrated circuit development.
|
||||||
|
@@ -26,13 +26,14 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cairo-output.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <cairo-pdf.h>
|
#include <cairo-pdf.h>
|
||||||
#include <cairo-svg.h>
|
#include <cairo-svg.h>
|
||||||
|
|
||||||
|
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The cairo_layer struct
|
* @brief The cairo_layer struct
|
||||||
* Each rendered layer is represented by this struct.
|
* Each rendered layer is represented by this struct.
|
||||||
@@ -235,8 +236,12 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
|||||||
/* Print size */
|
/* Print size */
|
||||||
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
|
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
|
||||||
&rec_width, &rec_height);
|
&rec_width, &rec_height);
|
||||||
printf("Size of layer %d: %lf -- %lf\n", linfo->layer,
|
printf("Size of layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n",
|
||||||
rec_width, rec_height);
|
linfo->layer,
|
||||||
|
(linfo->name && linfo->name[0] ? " (" : ""),
|
||||||
|
(linfo->name && linfo->name[0] ? linfo->name : ""),
|
||||||
|
(linfo->name && linfo->name[0] ? ")" : ""),
|
||||||
|
rec_width, rec_height, rec_x0, rec_y0);
|
||||||
|
|
||||||
/* update bounding box */
|
/* update bounding box */
|
||||||
xmin = MIN(xmin, rec_x0);
|
xmin = MIN(xmin, rec_x0);
|
||||||
@@ -250,7 +255,7 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Bounding box: (%lf,%lf) -- (%lf,%lf)\n", xmin, ymin, xmax, ymax);
|
printf("Cell bounding box: (%lf | %lf) -- (%lf | %lf)\n", xmin, ymin, xmax, ymax);
|
||||||
|
|
||||||
if (pdf_file) {
|
if (pdf_file) {
|
||||||
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
|
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
|
@@ -24,18 +24,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup cmdline
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "command-line.h"
|
|
||||||
#include "gds-parser/gds-parser.h"
|
#include <gds-render/command-line.h>
|
||||||
#include "mapping-parser.h"
|
#include <gds-render/gds-utils/gds-parser.h>
|
||||||
#include "cairo-output/cairo-output.h"
|
#include <gds-render/layer/mapping-parser.h>
|
||||||
#include "latex-output/latex-output.h"
|
#include <gds-render/layer/layer-info.h>
|
||||||
#include "external-renderer.h"
|
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||||
#include "gds-parser/gds-tree-checker.h"
|
#include <gds-render/latex-renderer/latex-output.h>
|
||||||
|
#include <gds-render/external-renderer.h>
|
||||||
|
#include <gds-render/gds-utils/gds-tree-checker.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete layer_info and free nem element.
|
* @brief Delete layer_info and free nem element.
|
||||||
@@ -97,7 +99,7 @@ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gb
|
|||||||
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
res = load_csv_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
|
res = mapping_parser_load_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (!layer_export)
|
if (!layer_export)
|
||||||
continue;
|
continue;
|
||||||
|
@@ -9,7 +9,7 @@ done
|
|||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
|
|
||||||
export PROJECT_NUMBER=`git describe --tags`
|
export PROJECT_NUMBER=`../version/generate-version-string.sh`
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
if [ $# != 1 ]; then
|
||||||
export OUTPUT_DIRECTORY="./output"
|
export OUTPUT_DIRECTORY="./output"
|
||||||
|
4
doxygen/cairo-renderer.dox
Normal file
4
doxygen/cairo-renderer.dox
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup Cairo-Renderer Cairo Renderer
|
||||||
|
* @ingroup renderers
|
||||||
|
*/
|
3
doxygen/command-line.dox
Normal file
3
doxygen/command-line.dox
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup cmdline Command Line Interface
|
||||||
|
*/
|
67
doxygen/compilation.dox
Normal file
67
doxygen/compilation.dox
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
|
||||||
|
@page compilation Compilation
|
||||||
|
|
||||||
|
@section Preface
|
||||||
|
|
||||||
|
GDS-Render is designed for UNIX-like, especially GNU/Linux based systems.
|
||||||
|
It was developed under a Linux system. Therefore, best performance is expected using a Linux operating system.
|
||||||
|
|
||||||
|
@section depencencies Dependencies
|
||||||
|
The dependencies of GDS-Render are:
|
||||||
|
|
||||||
|
@subsection run-deps Program Dependencies
|
||||||
|
|
||||||
|
- GLib2
|
||||||
|
- GTK3
|
||||||
|
- Cairographics
|
||||||
|
|
||||||
|
@subsection comp-deps Compilation Dependencies
|
||||||
|
These dependencies are not needed for running the program; just for compilation.
|
||||||
|
|
||||||
|
- Build System (GCC + binutils, make, etc...). Most distributions supply a "development" meta-package containing this stuff.
|
||||||
|
- cmake >= 2.8
|
||||||
|
- More or less optional: git. Used for extraction of the precise version number. It is strongly recommended to provide git!
|
||||||
|
- Optional: doxygen for this nice documentation.
|
||||||
|
|
||||||
|
The dependency list of GTK3 already includes Cairographics and GLib2. You should be on the safe side with a recent GTK3 version.
|
||||||
|
|
||||||
|
Development is done with the following library versions:
|
||||||
|
|
||||||
|
| Cairographics | GLib2 | GTK3 |
|
||||||
|
| ------------- | ---------- | ------ |
|
||||||
|
| 1.16.0-2 | 2.60.0-1 | 3.24.7 |
|
||||||
|
|
||||||
|
@section comp-instr Compilation Instructions
|
||||||
|
@subsection linux-build General Linux Build Instruction
|
||||||
|
Go to the build directory you want to compile in. This may be the gds-render project root.
|
||||||
|
Execute
|
||||||
|
@code
|
||||||
|
cmake <Path to gds-render root>
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Cmake will check the dependencies. Once cmake has finished. Type
|
||||||
|
|
||||||
|
@code
|
||||||
|
make
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
in order to build the program and
|
||||||
|
|
||||||
|
@code
|
||||||
|
make documentation
|
||||||
|
@endcode
|
||||||
|
to build the doxygen documentation.
|
||||||
|
|
||||||
|
@subsection arch-makepkg Archlinux Package
|
||||||
|
|
||||||
|
The subfolder 'AUR' contains a PKGBUILD file to build an Archlinux/Pacman package.
|
||||||
|
|
||||||
|
@subsection Compiler Warnings
|
||||||
|
|
||||||
|
The compiler will throw the following warnings. Compiled with GCC 8.2.1.
|
||||||
|
|
||||||
|
| Warning | Assessment |
|
||||||
|
| ------- | ---------- |
|
||||||
|
| warning: ‘calculate_path_miter_points’ defined but not used [-Wunused-function] | Ignore. Function will be used in later versions. |
|
||||||
|
*/
|
4
doxygen/external-renderer.dox
Normal file
4
doxygen/external-renderer.dox
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup external-renderer External Shared Object Renderer
|
||||||
|
* @ingroup renderers
|
||||||
|
*/
|
@@ -1,8 +1,8 @@
|
|||||||
/* This file only contains help information for doxygen */
|
/* This file only contains help information for doxygen */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup trigonometric Trigonometric Helper Functions
|
* @defgroup geometric Geometric Helper Functions
|
||||||
*
|
*
|
||||||
* The trigonometric helper function are used to calculate bounding boxes
|
* The geometric helper function are used to calculate bounding boxes
|
||||||
* @warning Code is incomplete. Please double check for functionality!
|
* @warning Code is incomplete. Please double check for functionality!
|
||||||
*/
|
*/
|
@@ -1,6 +1,5 @@
|
|||||||
/* This file only contains help information for doxygen */
|
/* This file only contains help information for doxygen */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup MainApplication Main Application
|
* @defgroup GUI Graphical User Interface
|
||||||
*
|
|
||||||
*/
|
*/
|
Binary file not shown.
BIN
doxygen/images/gui.png
Normal file
BIN
doxygen/images/gui.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 114 KiB |
4
doxygen/latex-renderer.dox
Normal file
4
doxygen/latex-renderer.dox
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup LaTeX-Renderer LaTeX/TikZ Renderer
|
||||||
|
* @ingroup renderers
|
||||||
|
*/
|
7
doxygen/layer-selector.dox
Normal file
7
doxygen/layer-selector.dox
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup layer-selector LayerSelector Object
|
||||||
|
* @ingroup GUI
|
||||||
|
*
|
||||||
|
* This objects implements the layer selector and displays the layers in a list box.
|
||||||
|
* It uses @ref LayerElement objects to display the individual layers inside the list box.
|
||||||
|
*/
|
18
doxygen/lib-cell-renderer.dox
Normal file
18
doxygen/lib-cell-renderer.dox
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup LibCellRenderer LibCellRenderer GObject
|
||||||
|
* @ingroup GUI
|
||||||
|
*
|
||||||
|
* The LibCellRenderer Object is used to render @ref gds_cell and @ref gds_library elements
|
||||||
|
* to a GtkTreeView.
|
||||||
|
*
|
||||||
|
* The LibCellRenderer class is derived from a GtkCellRendererText and works the same way.
|
||||||
|
* The additinal features are three new properties:
|
||||||
|
*
|
||||||
|
* - *gds-lib*: This property can be used to set a @ref gds_library structure. The renderer will render the name of the library.
|
||||||
|
* - *gds-cell*: This property can be used to set a @ref gds_cell structure. The renderer will render the name of the cell.
|
||||||
|
* - *error-level*: Set the error level of the cell/library. This affects the foreground color of hte rendered output.
|
||||||
|
*
|
||||||
|
* Internally the class operates by setting the 'text' property, which is inherited form the base class to the library/cell name (gds_library::name and gds_cell::name fields).
|
||||||
|
* The error level (@ref LIB_CELL_RENDERER_ERROR_WARN and @ref LIB_CELL_RENDERER_ERROR_ERR) is translated to the inherited 'foreground-rgba' property.
|
||||||
|
*
|
||||||
|
*/
|
@@ -6,10 +6,7 @@ This programm converts GDS layout files to
|
|||||||
- PDF Files using the @ref Cairo-Renderer
|
- PDF Files using the @ref Cairo-Renderer
|
||||||
- Latex code (TikZ) using the @ref LaTeX-Renderer
|
- Latex code (TikZ) using the @ref LaTeX-Renderer
|
||||||
|
|
||||||
See the @subpage usage page for details
|
See the @subpage usage page for details and @subpage compilation for building instructions and @subpage versioning for the versioning scheme of this program.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
9
doxygen/renderers.dox
Normal file
9
doxygen/renderers.dox
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup renderers Output Renderers
|
||||||
|
*
|
||||||
|
* The renderers are used to convert the cell structures read from the GDS layout file
|
||||||
|
* into different output formats.
|
||||||
|
*
|
||||||
|
* Currently the renders are statically implemented without the use of GObjects.
|
||||||
|
* This will probably change in future releases in order to make it easier to integrate new rendering methods.
|
||||||
|
*/
|
@@ -1,21 +1,21 @@
|
|||||||
/**
|
/**
|
||||||
@page usage Usage
|
@page usage Usage
|
||||||
@section cmd Command Line Interface
|
@section cmd Command Line Interface
|
||||||
To use the application on the command line check 'gds-render --help'.
|
To use the application on the command line check 'gds-render `--`help'.
|
||||||
|
|
||||||
Application Options:
|
Application Options:
|
||||||
- -t, --tikz Output TikZ code
|
- -t, `--`tikz Output TikZ code
|
||||||
- -p, --pdf Output PDF document
|
- -p, `--`pdf Output PDF document
|
||||||
- -s, --scale=SCALE Divide output coordinates by SCALE
|
- -s, `--`scale=SCALE Divide output coordinates by SCALE
|
||||||
- -o, --tex-output=PATH Optional path for TeX file
|
- -o, `--`tex-output=PATH Optional path for TeX file
|
||||||
- -O, --pdf-output=PATH Optional path for PDF file
|
- -O, `--`pdf-output=PATH Optional path for PDF file
|
||||||
- -m, --mapping=PATH Path for Layer Mapping File
|
- -m, `--`mapping=PATH Path for Layer Mapping File
|
||||||
- -c, --cell=NAME Cell to render
|
- -c, `--`cell=NAME Cell to render
|
||||||
- -a, --tex-standalone Create standalone PDF
|
- -a, `--`tex-standalone Create standalone PDF
|
||||||
- -l, --tex-layers Create PDF Layers (OCG)
|
- -l, `--`tex-layers Create PDF Layers (OCG)
|
||||||
- -P, --custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
|
- -P, `--`custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
|
||||||
- -e, --external-lib-output=PATH Output path for external render library
|
- -e, `--`external-lib-output=PATH Output path for external render library
|
||||||
- --display=DISPLAY X display to use
|
- `--`display=DISPLAY X display to use
|
||||||
|
|
||||||
|
|
||||||
@section gui Graphical User Interface
|
@section gui Graphical User Interface
|
||||||
@@ -24,7 +24,11 @@ The graphical user interface (GUI) can be used to open GDS Files, configure the
|
|||||||
|
|
||||||
It is possible to export the layer configurations so they can be used later on. Even in the @ref cmd
|
It is possible to export the layer configurations so they can be used later on. Even in the @ref cmd
|
||||||
|
|
||||||
@image html gui.svg
|
@image html gui.png
|
||||||
@image latex gui.pdf
|
@image latex gui.png
|
||||||
|
|
||||||
|
The cell selector on the left shows the GDS Libraries and Cells. The cells are marked green if all references inside the cell could be found. If not all references could be found, the cell is marked orange. This doens't show if child cells have missing childs. Only one level of the hierarchy is checked in order to make it easier to spot an errorneous cell. Cells with missing child cells are still renderable but -- obviously -- faulty. If a cell or any sub-cell contains a reference loop, the cell is marked red. In this case it can't be selected for rendering.
|
||||||
|
|
||||||
|
In the above image the cell is green; so everything is okay.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
36
doxygen/versioning.dox
Normal file
36
doxygen/versioning.dox
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
@page versioning Version Number
|
||||||
|
|
||||||
|
@section main-version Main Versioning Scheme
|
||||||
|
The version number of this application consists of a given version in the format of 'v1.0'.
|
||||||
|
Where the first number indicates a major release and the second number indicates minor changes.
|
||||||
|
|
||||||
|
Versions, including release candidates and path-levels, are tagged in git.
|
||||||
|
|
||||||
|
@subsection rc Release Candidates
|
||||||
|
Release candidates are software versions that seem stable and functional to become a new version but testing is not fully finished. These versions are marked with an '-rcX', where X is the number of the release candidate.
|
||||||
|
The 3rd release candidate of version 4.2 would be '*v4.2-rc3*'.
|
||||||
|
Release candidates are in a frozen state. Only bugfixes that are necessary for functionality are applied to these versions before releasing the final version.
|
||||||
|
|
||||||
|
@subsection patch-level Patch Levels
|
||||||
|
If an already released version contains bugs that need to be fixed, the version number is not incremented. Insted a new version number with a patch-level is created. The patch-level is appended with a dash directly after the version number. The fist patch-level of version 3.5 would be: 'v3.5-1'.
|
||||||
|
|
||||||
|
|
||||||
|
@section git-version-num Git Based Version Number
|
||||||
|
|
||||||
|
The application and this documentation contain a git-based version number. With this version number not only released versions but all development points of the software can be uniquely identified.
|
||||||
|
|
||||||
|
An example for such a version number is: *v1.0-rc4-41-gaa41373-dirty*
|
||||||
|
|
||||||
|
It consists of the last @ref main-version (in this case version 1.0 -- Release candidate 4) and some other information from the source code management system. The number after the version tag is the commit count after the given version. In this case the specified version is 41 commits after the last tagged version 'v1.0-rc4'. The next section always starts with a 'g' (for git) and after that contains the first letters of the commit ID. In this case an additional '-dirty' is appended, showing that the software version contains unstaged changes.
|
||||||
|
|
||||||
|
In tabular form: *v1.0-rc4-41-gaa41373-dirty*
|
||||||
|
|
||||||
|
| Last tagged version | Commits since that version | Start of commit ID | Unstaged changes? |
|
||||||
|
|---------------------|----------------------------|--------------------|---------------------|
|
||||||
|
| 1.0-rc4 | 41 | aa41373 | yes |
|
||||||
|
|
||||||
|
|
||||||
|
This git-based version number is automatically put into the application and this doxumentation during the application's compilation / the documentation's generation. For this *git* is needed. Therefore, it is highly recommended to have 'git' installed for compilation although it is no build dependency. In case of a missing git installation, the string "! version not set !" is compiled into the application.
|
||||||
|
|
||||||
|
**/
|
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup Widgets Custom GTK Widgets
|
* @defgroup Widgets Custom GTK Widgets
|
||||||
*
|
* @ingroup GUI
|
||||||
*/
|
*/
|
||||||
|
@@ -24,14 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup external-renderer
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "external-renderer.h"
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <gds-render/external-renderer.h>
|
||||||
|
|
||||||
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list,
|
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list,
|
||||||
char *output_file, char *so_path)
|
char *output_file, char *so_path)
|
||||||
{
|
{
|
||||||
|
559
gds-render-gui.c
Normal file
559
gds-render-gui.c
Normal file
@@ -0,0 +1,559 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file gds-render-gui.c
|
||||||
|
* @brief Handling of GUI
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup GUI
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <gds-render/gds-render-gui.h>
|
||||||
|
#include <gds-render/gds-utils/gds-parser.h>
|
||||||
|
#include <gds-render/gds-utils/gds-tree-checker.h>
|
||||||
|
#include <gds-render/layer/layer-selector.h>
|
||||||
|
#include <gds-render/tree-renderer/tree-store.h>
|
||||||
|
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||||
|
#include <gds-render/latex-renderer/latex-output.h>
|
||||||
|
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||||
|
#include <gds-render/widgets/conv-settings-dialog.h>
|
||||||
|
#include <gds-render/geometric/cell-geometrics.h>
|
||||||
|
#include <gds-render/version.h>
|
||||||
|
|
||||||
|
enum gds_render_gui_signal_sig_ids {SIGNAL_WINDOW_CLOSED = 0, SIGNAL_COUNT};
|
||||||
|
|
||||||
|
static guint gds_render_gui_signals[SIGNAL_COUNT];
|
||||||
|
|
||||||
|
struct _GdsRenderGui {
|
||||||
|
/* Parent GObject */
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
/* Custom fields */
|
||||||
|
GtkWindow *main_window;
|
||||||
|
GtkWidget *convert_button;
|
||||||
|
GtkTreeStore *cell_tree_store;
|
||||||
|
GtkWidget *cell_search_entry;
|
||||||
|
LayerSelector *layer_selector;
|
||||||
|
GtkTreeView *cell_tree_view;
|
||||||
|
GList *gds_libraries;
|
||||||
|
struct render_settings render_dialog_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main window close event
|
||||||
|
* @param window GtkWindow which is closed
|
||||||
|
* @param event unused event
|
||||||
|
* @param user GdsRenderGui instance
|
||||||
|
* @return Status of the event handling. Always true.
|
||||||
|
*/
|
||||||
|
static gboolean on_window_close(gpointer window, GdkEvent *event, gpointer user)
|
||||||
|
{
|
||||||
|
GdsRenderGui *self;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(user);
|
||||||
|
/* Don't close window in case of error */
|
||||||
|
if (!self)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* Close Window. Leads to termination of the program/the current instance */
|
||||||
|
g_clear_object(&self->main_window);
|
||||||
|
gtk_widget_destroy(GTK_WIDGET(window));
|
||||||
|
|
||||||
|
/* Delete loaded library data */
|
||||||
|
clear_lib_list(&self->gds_libraries);
|
||||||
|
|
||||||
|
g_signal_emit(self, gds_render_gui_signals[SIGNAL_WINDOW_CLOSED], 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief generate string from gds_time_field
|
||||||
|
* @param date Date to convert
|
||||||
|
* @return String with date
|
||||||
|
*/
|
||||||
|
static GString *generate_string_from_date(struct gds_time_field *date)
|
||||||
|
{
|
||||||
|
GString *str;
|
||||||
|
|
||||||
|
str = g_string_new_len(NULL, 50);
|
||||||
|
g_string_printf(str, "%02u.%02u.%u - %02u:%02u",
|
||||||
|
(unsigned int)date->day,
|
||||||
|
(unsigned int)date->month,
|
||||||
|
(unsigned int)date->year,
|
||||||
|
(unsigned int)date->hour,
|
||||||
|
(unsigned int)date->minute);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function of Load GDS button
|
||||||
|
* @param button
|
||||||
|
* @param user GdsRenderGui instance
|
||||||
|
*/
|
||||||
|
static void on_load_gds(gpointer button, gpointer user)
|
||||||
|
{
|
||||||
|
GList *cell;
|
||||||
|
GtkTreeIter libiter;
|
||||||
|
GtkTreeIter celliter;
|
||||||
|
GList *lib;
|
||||||
|
struct gds_library *gds_lib;
|
||||||
|
struct gds_cell *gds_c;
|
||||||
|
GdsRenderGui *self;
|
||||||
|
GtkWidget *open_dialog;
|
||||||
|
GtkFileChooser *file_chooser;
|
||||||
|
GtkFileFilter *filter;
|
||||||
|
GtkStyleContext *button_style;
|
||||||
|
gint dialog_result;
|
||||||
|
int gds_result;
|
||||||
|
char *filename;
|
||||||
|
GString *mod_date;
|
||||||
|
GString *acc_date;
|
||||||
|
unsigned int cell_error_level;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(user);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", self->main_window,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
"Cancel", GTK_RESPONSE_CANCEL,
|
||||||
|
"Open GDSII", GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
file_chooser = GTK_FILE_CHOOSER(open_dialog);
|
||||||
|
|
||||||
|
/* Add GDS II Filter */
|
||||||
|
filter = gtk_file_filter_new();
|
||||||
|
gtk_file_filter_add_pattern(filter, "*.gds");
|
||||||
|
gtk_file_filter_set_name(filter, "GDSII-Files");
|
||||||
|
gtk_file_chooser_add_filter(file_chooser, filter);
|
||||||
|
|
||||||
|
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
|
||||||
|
|
||||||
|
if (dialog_result != GTK_RESPONSE_ACCEPT)
|
||||||
|
goto end_destroy;
|
||||||
|
|
||||||
|
/* Get File name */
|
||||||
|
filename = gtk_file_chooser_get_filename(file_chooser);
|
||||||
|
|
||||||
|
gtk_tree_store_clear(self->cell_tree_store);
|
||||||
|
clear_lib_list(&self->gds_libraries);
|
||||||
|
|
||||||
|
/* Parse new GDSII file */
|
||||||
|
gds_result = parse_gds_from_file(filename, &self->gds_libraries);
|
||||||
|
|
||||||
|
/* Delete file name afterwards */
|
||||||
|
g_free(filename);
|
||||||
|
if (gds_result)
|
||||||
|
goto end_destroy;
|
||||||
|
|
||||||
|
/* remove suggested action from Open button */
|
||||||
|
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
|
||||||
|
gtk_style_context_remove_class(button_style, "suggested-action");
|
||||||
|
|
||||||
|
for (lib = self->gds_libraries; lib != NULL; lib = lib->next) {
|
||||||
|
gds_lib = (struct gds_library *)lib->data;
|
||||||
|
/* Create top level iter */
|
||||||
|
gtk_tree_store_append(self->cell_tree_store, &libiter, NULL);
|
||||||
|
|
||||||
|
/* Convert dates to String */
|
||||||
|
mod_date = generate_string_from_date(&gds_lib->mod_time);
|
||||||
|
acc_date = generate_string_from_date(&gds_lib->access_time);
|
||||||
|
|
||||||
|
gtk_tree_store_set(self->cell_tree_store, &libiter,
|
||||||
|
CELL_SEL_LIBRARY, gds_lib,
|
||||||
|
CELL_SEL_MODDATE, mod_date->str,
|
||||||
|
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
/* Check this library. This might take a while */
|
||||||
|
(void)gds_tree_check_cell_references(gds_lib);
|
||||||
|
(void)gds_tree_check_reference_loops(gds_lib);
|
||||||
|
/* Delete GStrings including string data. */
|
||||||
|
/* Cell store copies String type data items */
|
||||||
|
g_string_free(mod_date, TRUE);
|
||||||
|
g_string_free(acc_date, TRUE);
|
||||||
|
|
||||||
|
for (cell = gds_lib->cells; cell != NULL; cell = cell->next) {
|
||||||
|
gds_c = (struct gds_cell *)cell->data;
|
||||||
|
gtk_tree_store_append(self->cell_tree_store, &celliter, &libiter);
|
||||||
|
/* Convert dates to String */
|
||||||
|
mod_date = generate_string_from_date(&gds_c->mod_time);
|
||||||
|
acc_date = generate_string_from_date(&gds_c->access_time);
|
||||||
|
|
||||||
|
/* Get the checking results for this cell */
|
||||||
|
cell_error_level = 0;
|
||||||
|
if (gds_c->checks.unresolved_child_count)
|
||||||
|
cell_error_level |= LIB_CELL_RENDERER_ERROR_WARN;
|
||||||
|
|
||||||
|
/* Check if it is completely b0rken */
|
||||||
|
if (gds_c->checks.affected_by_reference_loop)
|
||||||
|
cell_error_level |= LIB_CELL_RENDERER_ERROR_ERR;
|
||||||
|
|
||||||
|
/* Add cell to tree store model */
|
||||||
|
gtk_tree_store_set(self->cell_tree_store, &celliter,
|
||||||
|
CELL_SEL_CELL, gds_c,
|
||||||
|
CELL_SEL_MODDATE, mod_date->str,
|
||||||
|
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||||
|
CELL_SEL_CELL_ERROR_STATE, cell_error_level,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
/* Delete GStrings including string data. */
|
||||||
|
/* Cell store copies String type data items */
|
||||||
|
g_string_free(mod_date, TRUE);
|
||||||
|
g_string_free(acc_date, TRUE);
|
||||||
|
} /* for cells */
|
||||||
|
} /* for libraries */
|
||||||
|
|
||||||
|
/* Create Layers in Layer Box */
|
||||||
|
layer_selector_generate_layer_widgets(self->layer_selector, self->gds_libraries);
|
||||||
|
|
||||||
|
end_destroy:
|
||||||
|
/* Destroy dialog and filter */
|
||||||
|
gtk_widget_destroy(open_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert button callback
|
||||||
|
* @param button
|
||||||
|
* @param user
|
||||||
|
*/
|
||||||
|
static void on_convert_clicked(gpointer button, gpointer user)
|
||||||
|
{
|
||||||
|
(void)button;
|
||||||
|
GdsRenderGui *self;
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
GList *layer_list;
|
||||||
|
struct gds_cell *cell_to_render;
|
||||||
|
FILE *output_file;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
RendererSettingsDialog *settings;
|
||||||
|
GtkFileFilter *filter;
|
||||||
|
gint res;
|
||||||
|
char *file_name;
|
||||||
|
union bounding_box cell_box;
|
||||||
|
unsigned int height, width;
|
||||||
|
struct render_settings *sett;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(user);
|
||||||
|
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sett = &self->render_dialog_settings;
|
||||||
|
|
||||||
|
/* Get selected cell */
|
||||||
|
selection = gtk_tree_view_get_selection(self->cell_tree_view);
|
||||||
|
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell_to_render, -1);
|
||||||
|
|
||||||
|
if (!cell_to_render)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Get layers that are rendered */
|
||||||
|
layer_list = layer_selector_export_rendered_layer_info(self->layer_selector);
|
||||||
|
|
||||||
|
/* Calculate cell size in DB units */
|
||||||
|
bounding_box_prepare_empty(&cell_box);
|
||||||
|
calculate_cell_bounding_box(&cell_box, cell_to_render);
|
||||||
|
|
||||||
|
/* Calculate size in database units
|
||||||
|
* Note that the results are bound to be positive,
|
||||||
|
* so casting them to unsigned int is absolutely valid
|
||||||
|
*/
|
||||||
|
height = (unsigned int)(cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y);
|
||||||
|
width = (unsigned int)(cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x);
|
||||||
|
|
||||||
|
/* Show settings dialog */
|
||||||
|
settings = renderer_settings_dialog_new(GTK_WINDOW(self->main_window));
|
||||||
|
renderer_settings_dialog_set_settings(settings, sett);
|
||||||
|
renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters);
|
||||||
|
renderer_settings_dialog_set_cell_height(settings, height);
|
||||||
|
renderer_settings_dialog_set_cell_width(settings, width);
|
||||||
|
g_object_set(G_OBJECT(settings), "cell-name", cell_to_render->name, NULL);
|
||||||
|
|
||||||
|
res = gtk_dialog_run(GTK_DIALOG(settings));
|
||||||
|
if (res == GTK_RESPONSE_OK) {
|
||||||
|
renderer_settings_dialog_get_settings(settings, sett);
|
||||||
|
gtk_widget_destroy(GTK_WIDGET(settings));
|
||||||
|
} else {
|
||||||
|
gtk_widget_destroy(GTK_WIDGET(settings));
|
||||||
|
goto ret_layer_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save file dialog */
|
||||||
|
dialog = gtk_file_chooser_dialog_new((sett->renderer == RENDERER_LATEX_TIKZ
|
||||||
|
? "Save LaTeX File" : "Save PDF"),
|
||||||
|
GTK_WINDOW(self->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
|
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
/* Set file filter according to settings */
|
||||||
|
filter = gtk_file_filter_new();
|
||||||
|
switch (sett->renderer) {
|
||||||
|
case RENDERER_LATEX_TIKZ:
|
||||||
|
gtk_file_filter_add_pattern(filter, "*.tex");
|
||||||
|
gtk_file_filter_set_name(filter, "LaTeX-Files");
|
||||||
|
break;
|
||||||
|
case RENDERER_CAIROGRAPHICS_PDF:
|
||||||
|
gtk_file_filter_add_pattern(filter, "*.pdf");
|
||||||
|
gtk_file_filter_set_name(filter, "PDF-Files");
|
||||||
|
break;
|
||||||
|
case RENDERER_CAIROGRAPHICS_SVG:
|
||||||
|
gtk_file_filter_add_pattern(filter, "*.svg");
|
||||||
|
gtk_file_filter_set_name(filter, "SVG-Files");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||||
|
|
||||||
|
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||||
|
|
||||||
|
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
|
if (res == GTK_RESPONSE_ACCEPT) {
|
||||||
|
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
|
||||||
|
switch (sett->renderer) {
|
||||||
|
case RENDERER_LATEX_TIKZ:
|
||||||
|
output_file = fopen(file_name, "w");
|
||||||
|
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett->scale,
|
||||||
|
sett->tex_pdf_layers, sett->tex_standalone);
|
||||||
|
fclose(output_file);
|
||||||
|
break;
|
||||||
|
case RENDERER_CAIROGRAPHICS_SVG:
|
||||||
|
case RENDERER_CAIROGRAPHICS_PDF:
|
||||||
|
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
||||||
|
(sett->renderer == RENDERER_CAIROGRAPHICS_PDF
|
||||||
|
? file_name
|
||||||
|
: NULL),
|
||||||
|
(sett->renderer == RENDERER_CAIROGRAPHICS_SVG
|
||||||
|
? file_name
|
||||||
|
: NULL),
|
||||||
|
sett->scale);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_free(file_name);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
}
|
||||||
|
ret_layer_destroy:
|
||||||
|
g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief cell_tree_view_activated Callback for 'double click' on cell selector element
|
||||||
|
* @param tree_view The tree view the event occured in
|
||||||
|
* @param path path to the selected row
|
||||||
|
* @param column The clicked column
|
||||||
|
* @param user pointer to GdsRenderGui object
|
||||||
|
*/
|
||||||
|
static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
|
||||||
|
GtkTreeViewColumn *column, gpointer user)
|
||||||
|
{
|
||||||
|
(void)tree_view;
|
||||||
|
(void)path;
|
||||||
|
(void)column;
|
||||||
|
|
||||||
|
on_convert_clicked(NULL, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for cell-selection change event
|
||||||
|
*
|
||||||
|
* This function activates/deactivates the convert button depending on whether
|
||||||
|
* a cell is selected for conversion or not
|
||||||
|
* @param sel
|
||||||
|
* @param self
|
||||||
|
*/
|
||||||
|
static void cell_selection_changed(GtkTreeSelection *sel, GdsRenderGui *self)
|
||||||
|
{
|
||||||
|
GtkTreeModel *model = NULL;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
|
||||||
|
/* Node selected. Show button */
|
||||||
|
gtk_widget_set_sensitive(self->convert_button, TRUE);
|
||||||
|
} else {
|
||||||
|
gtk_widget_set_sensitive(self->convert_button, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sort_up_callback(GtkWidget *widget, gpointer user)
|
||||||
|
{
|
||||||
|
(void)widget;
|
||||||
|
GdsRenderGui *self;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(user);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
layer_selector_force_sort(self->layer_selector, LAYER_SELECTOR_SORT_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sort_down_callback(GtkWidget *widget, gpointer user)
|
||||||
|
{
|
||||||
|
(void)widget;
|
||||||
|
GdsRenderGui *self;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(user);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
layer_selector_force_sort(self->layer_selector, LAYER_SELECTOR_SORT_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gds_render_gui_dispose(GObject *gobject)
|
||||||
|
{
|
||||||
|
GdsRenderGui *self;
|
||||||
|
|
||||||
|
self = RENDERER_GUI(gobject);
|
||||||
|
|
||||||
|
clear_lib_list(&self->gds_libraries);
|
||||||
|
|
||||||
|
g_clear_object(&self->cell_tree_view);
|
||||||
|
g_clear_object(&self->convert_button);
|
||||||
|
g_clear_object(&self->layer_selector);
|
||||||
|
g_clear_object(&self->cell_tree_store);
|
||||||
|
g_clear_object(&self->cell_search_entry);
|
||||||
|
|
||||||
|
if (self->main_window) {
|
||||||
|
g_signal_handlers_destroy(self->main_window);
|
||||||
|
gtk_widget_destroy(GTK_WIDGET(self->main_window));
|
||||||
|
self->main_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chain up */
|
||||||
|
G_OBJECT_CLASS(gds_render_gui_parent_class)->dispose(gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gds_render_gui_class_init(GdsRenderGuiClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
gds_render_gui_signals[SIGNAL_WINDOW_CLOSED] =
|
||||||
|
g_signal_newv("window-closed", RENDERER_TYPE_GUI,
|
||||||
|
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
gobject_class->dispose = gds_render_gui_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWindow *gds_render_gui_get_main_window(GdsRenderGui *gui)
|
||||||
|
{
|
||||||
|
return gui->main_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gds_render_gui_init(GdsRenderGui *self)
|
||||||
|
{
|
||||||
|
GtkBuilder *main_builder;
|
||||||
|
GtkWidget *listbox;
|
||||||
|
GtkHeaderBar *header_bar;
|
||||||
|
struct tree_stores *cell_selector_stores;
|
||||||
|
GtkWidget *sort_up_button;
|
||||||
|
GtkWidget *sort_down_button;
|
||||||
|
|
||||||
|
main_builder = gtk_builder_new_from_resource("/main.glade");
|
||||||
|
|
||||||
|
self->cell_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree"));
|
||||||
|
self->cell_search_entry = GTK_WIDGET(gtk_builder_get_object(main_builder, "cell-search"));
|
||||||
|
|
||||||
|
cell_selector_stores = setup_cell_selector(self->cell_tree_view, GTK_ENTRY(self->cell_search_entry));
|
||||||
|
|
||||||
|
self->cell_tree_store = cell_selector_stores->base_store;
|
||||||
|
|
||||||
|
self->main_window = GTK_WINDOW(gtk_builder_get_object(main_builder, "main-window"));
|
||||||
|
g_signal_connect(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds")),
|
||||||
|
"clicked", G_CALLBACK(on_load_gds), (gpointer)self);
|
||||||
|
|
||||||
|
self->convert_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
|
||||||
|
g_signal_connect(self->convert_button, "clicked", G_CALLBACK(on_convert_clicked), (gpointer)self);
|
||||||
|
|
||||||
|
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
|
||||||
|
/* Create layer selector */
|
||||||
|
self->layer_selector = layer_selector_new(GTK_LIST_BOX(listbox));
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback for selection change of cell selector */
|
||||||
|
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(self->cell_tree_view)), "changed",
|
||||||
|
G_CALLBACK(cell_selection_changed), self);
|
||||||
|
g_signal_connect(self->cell_tree_view, "row-activated", G_CALLBACK(cell_tree_view_activated), self);
|
||||||
|
|
||||||
|
/* Set version in main window subtitle */
|
||||||
|
header_bar = GTK_HEADER_BAR(gtk_builder_get_object(main_builder, "header-bar"));
|
||||||
|
gtk_header_bar_set_subtitle(header_bar, _app_version_string);
|
||||||
|
|
||||||
|
/* Get layer sorting buttons and set callbacks */
|
||||||
|
sort_up_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-up-sort"));
|
||||||
|
sort_down_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-down-sort"));
|
||||||
|
|
||||||
|
g_signal_connect(sort_up_button, "clicked", G_CALLBACK(sort_up_callback), self);
|
||||||
|
g_signal_connect(sort_down_button, "clicked", G_CALLBACK(sort_down_callback), self);
|
||||||
|
|
||||||
|
/* Set buttons for loading and saving */
|
||||||
|
layer_selector_set_load_mapping_button(self->layer_selector,
|
||||||
|
GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping")),
|
||||||
|
self->main_window);
|
||||||
|
layer_selector_set_save_mapping_button(self->layer_selector, GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping")),
|
||||||
|
self->main_window);
|
||||||
|
|
||||||
|
/* Connect delete-event */
|
||||||
|
g_signal_connect(GTK_WIDGET(self->main_window), "delete-event",
|
||||||
|
G_CALLBACK(on_window_close), self);
|
||||||
|
|
||||||
|
g_object_unref(main_builder);
|
||||||
|
|
||||||
|
/* Set default conversion/rendering settings */
|
||||||
|
self->render_dialog_settings.scale = 1000;
|
||||||
|
self->render_dialog_settings.renderer = RENDERER_LATEX_TIKZ;
|
||||||
|
self->render_dialog_settings.tex_pdf_layers = FALSE;
|
||||||
|
self->render_dialog_settings.tex_standalone = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
/* Reference all objects referenced by this object */
|
||||||
|
g_object_ref(self->main_window);
|
||||||
|
g_object_ref(self->cell_tree_view);
|
||||||
|
g_object_ref(self->convert_button);
|
||||||
|
g_object_ref(self->layer_selector);
|
||||||
|
g_object_ref(self->cell_tree_store);
|
||||||
|
g_object_ref(self->cell_search_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdsRenderGui *gds_render_gui_new()
|
||||||
|
{
|
||||||
|
return RENDERER_GUI(g_object_new(RENDERER_TYPE_GUI, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
@@ -34,8 +34,6 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "gds-parser.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -43,6 +41,8 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
|
#include <gds-render/gds-utils/gds-parser.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default units assumed for library.
|
* @brief Default units assumed for library.
|
||||||
* @note This value is usually overwritten with the value defined in the library.
|
* @note This value is usually overwritten with the value defined in the library.
|
@@ -33,9 +33,10 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gds-tree-checker.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <gds-render/gds-utils/gds-tree-checker.h>
|
||||||
|
|
||||||
int gds_tree_check_cell_references(struct gds_library *lib)
|
int gds_tree_check_cell_references(struct gds_library *lib)
|
||||||
{
|
{
|
||||||
GList *cell_iter;
|
GList *cell_iter;
|
@@ -24,14 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "bounding-box.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <gds-render/geometric/bounding-box.h>
|
||||||
|
|
||||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
||||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
||||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
@@ -18,16 +18,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file cell-trigonometrics.c
|
* @file cell-geometrics.c
|
||||||
* @brief Calculation of gds_cell trigonometrics
|
* @brief Calculation of gds_cell trigonometrics
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cell-trigonometrics.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <gds-render/geometric/cell-geometrics.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
@@ -24,14 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vector-operations.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <gds-render/geometric/vector-operations.h>
|
||||||
|
|
||||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
||||||
|
|
||||||
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)
|
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)
|
@@ -1,6 +1,7 @@
|
|||||||
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
|
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
|
||||||
add_custom_command(DEPENDS
|
add_custom_command(DEPENDS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.glade
|
${CMAKE_CURRENT_SOURCE_DIR}/*.glade
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/resources.xml
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/resources.c
|
${CMAKE_CURRENT_BINARY_DIR}/resources.c
|
||||||
COMMAND
|
COMMAND
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
<property name="website">https://git.shimatta.de/mhu/gds-render</property>
|
<property name="website">https://git.shimatta.de/mhu/gds-render</property>
|
||||||
<property name="website_label" translatable="yes">Git Repository</property>
|
<property name="website_label" translatable="yes">Git Repository</property>
|
||||||
<property name="authors">Mario Hüttel <mario.huettel@gmx.net></property>
|
<property name="authors">Mario Hüttel <mario.huettel@gmx.net></property>
|
||||||
<property name="logo_icon_name">gds-render</property>
|
<property name="logo_icon_name"/>
|
||||||
<property name="license_type">gpl-2-0-only</property>
|
<property name="license_type">gpl-2-0-only</property>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="latex-radio">
|
<object class="GtkRadioButton" id="latex-radio">
|
||||||
<property name="label" translatable="yes">Generate LaTeX/TikZ output</property>
|
<property name="label" translatable="yes">Generate LaTeX/TikZ output</property>
|
||||||
<property name="use_action_appearance">True</property>
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
@@ -32,11 +31,9 @@
|
|||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="cairo-pdf-radio">
|
<object class="GtkRadioButton" id="cairo-pdf-radio">
|
||||||
<property name="label" translatable="yes">Render PDF using Cairographics</property>
|
<property name="label" translatable="yes">Render PDF using Cairographics</property>
|
||||||
<property name="use_action_appearance">True</property>
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
<property name="active">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
<property name="group">latex-radio</property>
|
<property name="group">latex-radio</property>
|
||||||
</object>
|
</object>
|
||||||
@@ -49,11 +46,10 @@
|
|||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="cairo-svg-radio">
|
<object class="GtkRadioButton" id="cairo-svg-radio">
|
||||||
<property name="label" translatable="yes">Render SVG using Cairographics (too buggy at the moment)</property>
|
<property name="label" translatable="yes">Render SVG using Cairographics (too buggy at the moment)</property>
|
||||||
<property name="use_action_appearance">True</property>
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
<property name="active">True</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
<property name="group">latex-radio</property>
|
<property name="group">latex-radio</property>
|
||||||
</object>
|
</object>
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
<file compressed="true">about.glade</file>
|
<file compressed="true">about.glade</file>
|
||||||
<file>layer-widget.glade</file>
|
<file>layer-widget.glade</file>
|
||||||
<file>dialog.glade</file>
|
<file>dialog.glade</file>
|
||||||
|
<file compressed="true" alias="logo.svg">../icon/gds-render.svg</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|
||||||
|
@@ -21,11 +21,11 @@
|
|||||||
* @brief Header File for Cairo output renderer
|
* @brief Header File for Cairo output renderer
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
#ifndef __CAIRO_OUTPUT_H__
|
#ifndef _CAIRO_OUTPUT_H_
|
||||||
#define __CAIRO_OUTPUT_H__
|
#define _CAIRO_OUTPUT_H_
|
||||||
|
|
||||||
#include "../layer-selector/layer-selector.h"
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
#include "../gds-parser/gds-types.h"
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
|
||||||
/** @addtogroup Cairo-Renderer
|
/** @addtogroup Cairo-Renderer
|
||||||
* @{
|
* @{
|
||||||
@@ -45,4 +45,4 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* __CAIRO_OUTPUT_H__ */
|
#endif /* _CAIRO_OUTPUT_H_ */
|
@@ -24,12 +24,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup cmdline
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _COMMAND_LINE_H_
|
#ifndef _COMMAND_LINE_H_
|
||||||
#define _COMMAND_LINE_H_
|
#define _COMMAND_LINE_H_
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +49,8 @@
|
|||||||
* @param so_name Path to shared object of custom renderer
|
* @param so_name Path to shared object of custom renderer
|
||||||
* @param so_out_file Output file path for custom renderer
|
* @param so_out_file Output file path for custom renderer
|
||||||
* @param svg_name SVG file name
|
* @param svg_name SVG file name
|
||||||
|
*
|
||||||
|
* @note This function is pretty damn retarded (Lots of parameters). Will be reworked when generating GObjects for renderers.
|
||||||
*/
|
*/
|
||||||
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
||||||
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
@@ -24,14 +24,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup external-renderer
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _EXTERNAL_RENDERER_H_
|
#ifndef _EXTERNAL_RENDERER_H_
|
||||||
#define _EXTERNAL_RENDERER_H_
|
#define _EXTERNAL_RENDERER_H_
|
||||||
|
|
||||||
#include "gds-parser/gds-types.h"
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
/**
|
/**
|
@@ -18,29 +18,44 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file main-window.h
|
* @file gds-render-gui.h
|
||||||
* @brief Header for main-window
|
* @brief Header for GdsRenderGui Object
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MAIN_WINDOW_H_
|
#ifndef _GDS_RENDER_GUI_
|
||||||
#define _MAIN_WINDOW_H_
|
#define _GDS_RENDER_GUI_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup GUI
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(GdsRenderGui, gds_render_gui, RENDERER, GUI, GObject);
|
||||||
|
|
||||||
|
#define RENDERER_TYPE_GUI (gds_render_gui_get_type())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create main window
|
* @brief Create new GdsRenderGui Object
|
||||||
*
|
* @return New object
|
||||||
* This function creates the main window and sets the necessary callback routines.
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
GtkWindow *create_main_window();
|
GdsRenderGui *gds_render_gui_new();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get main window
|
||||||
|
*
|
||||||
|
* This function returns the main window of the GUI, which can later be displayed.
|
||||||
|
* All handling of hte GUI is taken care of inside the GdsRenderGui Object
|
||||||
|
* @return The generated main window
|
||||||
|
*/
|
||||||
|
GtkWindow *gds_render_gui_get_main_window(GdsRenderGui *gui);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* _MAIN_WINDOW_H_ */
|
#endif /* _GDS_RENDER_GUI_ */
|
@@ -28,11 +28,12 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GDSPARSE_H__
|
#ifndef _GDSPARSER_H_
|
||||||
#define __GDSPARSE_H__
|
#define _GDSPARSER_H_
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "gds-types.h"
|
|
||||||
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
|
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
|
||||||
|
|
||||||
@@ -46,4 +47,4 @@ int clear_lib_list(GList **library_list);
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* __GDSPARSE_H__ */
|
#endif /* _GDSPARSE_H_ */
|
@@ -31,7 +31,7 @@
|
|||||||
#ifndef _GDS_TREE_CHECKER_H_
|
#ifndef _GDS_TREE_CHECKER_H_
|
||||||
#define _GDS_TREE_CHECKER_H_
|
#define _GDS_TREE_CHECKER_H_
|
||||||
|
|
||||||
#include "gds-types.h"
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gds_tree_check_cell_references checks if all child cell references can be resolved in the given library
|
* @brief gds_tree_check_cell_references checks if all child cell references can be resolved in the given library
|
@@ -69,8 +69,8 @@ struct gds_point {
|
|||||||
* @brief Stores the result of the cell checks.
|
* @brief Stores the result of the cell checks.
|
||||||
*/
|
*/
|
||||||
struct gds_cell_checks {
|
struct gds_cell_checks {
|
||||||
int unresolved_child_count; /**< @brief Number of unresolved cell instances inside this cell. Default: GDS_CELL_CHECK_NOT_RUN */
|
int unresolved_child_count; /**< @brief Number of unresolved cell instances inside this cell. Default: @ref GDS_CELL_CHECK_NOT_RUN */
|
||||||
int affected_by_reference_loop; /**< @brief 1 if the cell is affected by a reference loop and therefore not renderable. Default: GDS_CELL_CHECK_NOT_RUN*/
|
int affected_by_reference_loop; /**< @brief 1 if the cell is affected by a reference loop and therefore not renderable. Default: @ref GDS_CELL_CHECK_NOT_RUN*/
|
||||||
/**
|
/**
|
||||||
* @brief For the internal use of the checker.
|
* @brief For the internal use of the checker.
|
||||||
* @warning Do not use this structure and its contents!
|
* @warning Do not use this structure and its contents!
|
@@ -24,14 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BOUNDING_BOX_H_
|
#ifndef _BOUNDING_BOX_H_
|
||||||
#define _BOUNDING_BOX_H_
|
#define _BOUNDING_BOX_H_
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "vector-operations.h"
|
#include <gds-render/geometric/vector-operations.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
union bounding_box {
|
union bounding_box {
|
@@ -18,30 +18,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file cell-trigonometrics.h
|
* @file cell-geometrics.h
|
||||||
* @brief Calculation of gds_cell trigonometrics
|
* @brief Calculation of gds_cell geometrics
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CELL_TRIGONOMETRICS_H_
|
#ifndef _CELL_GEOMETRICS_H_
|
||||||
#define _CELL_TRIGONOMETRICS_H_
|
#define _CELL_GEOMETRICS_H_
|
||||||
|
|
||||||
#include "bounding-box.h"
|
#include <gds-render/geometric/bounding-box.h>
|
||||||
#include "../gds-parser/gds-types.h"
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief calculate_cell_bounding_box Calculate bounding box of gds cell
|
* @brief calculate_cell_bounding_box Calculate bounding box of gds cell
|
||||||
* @param box Resulting boundig box. Will be uüdated and not overwritten
|
* @param box Resulting boundig box. Will be uüdated and not overwritten
|
||||||
* @param cell toplevel cell
|
* @param cell Toplevel cell
|
||||||
* @warning Path handling not yet implemented correctly
|
* @warning Path handling not yet implemented correctly.
|
||||||
*/
|
*/
|
||||||
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell);
|
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell);
|
||||||
|
|
||||||
#endif /* _CELL_TRIGONOMETRICS_H_ */
|
#endif /* _CELL_GEOMETRICS_H_ */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup trigonometric
|
* @addtogroup geometric
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
@@ -31,10 +31,11 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../gds-parser/gds-types.h"
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "../mapping-parser.h"
|
|
||||||
|
#include "gds-render/layer/layer-info.h"
|
||||||
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
#define LATEX_LINE_BUFFER_KB (10) /**< @brief Buffer for LaTeX Code line in KiB */
|
#define LATEX_LINE_BUFFER_KB (10) /**< @brief Buffer for LaTeX Code line in KiB */
|
||||||
|
|
51
include/gds-render/layer/layer-info.h
Normal file
51
include/gds-render/layer/layer-info.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file layer-info.h
|
||||||
|
* @brief Helper functions and definition of layer info struct
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LAYER_INFO_H_
|
||||||
|
#define _LAYER_INFO_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Layer information.
|
||||||
|
*
|
||||||
|
* This structs contains information on how to render a layer
|
||||||
|
*/
|
||||||
|
struct layer_info
|
||||||
|
{
|
||||||
|
int layer; /**< @brief Layer number */
|
||||||
|
char *name; /**< @brief Layer name */
|
||||||
|
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
||||||
|
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete a layer_info struct
|
||||||
|
* @param info Struct to be deleted.
|
||||||
|
* @note The layer_info::name Element has to be freed manually
|
||||||
|
*/
|
||||||
|
void layer_info_delete_struct(struct layer_info *info);
|
||||||
|
|
||||||
|
#endif // _LAYER_INFO_H_
|
97
include/gds-render/layer/layer-selector.h
Normal file
97
include/gds-render/layer/layer-selector.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file layer-selector.h
|
||||||
|
* @brief Implementation of the Layer selection list
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup layer-selector
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LAYER_SELECTOR_H__
|
||||||
|
#define __LAYER_SELECTOR_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(LayerSelector, layer_selector, LAYER, SELECTOR, GObject);
|
||||||
|
|
||||||
|
#define TYPE_LAYER_SELECTOR (layer_selector_get_type())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines how to sort the layer selector list box.
|
||||||
|
*/
|
||||||
|
enum layer_selector_sort_algo {LAYER_SELECTOR_SORT_DOWN = 0, LAYER_SELECTOR_SORT_UP};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief layer_selector_new
|
||||||
|
* @param list_box The associated list box, the content is displayed in
|
||||||
|
* @return Newly created layer selector
|
||||||
|
*/
|
||||||
|
LayerSelector *layer_selector_new(GtkListBox *list_box);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate layer widgets in in the LayerSelector instance
|
||||||
|
* @note This clears all previously inserted elements
|
||||||
|
* @param selector LayerSelector instance
|
||||||
|
* @param libs The libraries to add
|
||||||
|
*/
|
||||||
|
void layer_selector_generate_layer_widgets(LayerSelector *selector, GList *libs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Supply button for loading the layer mapping
|
||||||
|
* @param selector LayerSelector instance
|
||||||
|
* @param button Load button. Will be referenced
|
||||||
|
* @param main_window Parent window for dialogs. Will be referenced
|
||||||
|
*/
|
||||||
|
void layer_selector_set_load_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Supply button for saving the layer mapping
|
||||||
|
* @param selector LayerSelector instance
|
||||||
|
* @param button Save button. Will be refeneced
|
||||||
|
* @param main_window Parent window for dialogs. Will be referenced
|
||||||
|
*/
|
||||||
|
void layer_selector_set_save_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a list of all layers that shall be exported when rendering the cells
|
||||||
|
* @param selector Layer selector instance
|
||||||
|
* @return List of layer_info structures containing the layer information
|
||||||
|
*/
|
||||||
|
GList *layer_selector_export_rendered_layer_info(LayerSelector *selector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force the layer selector list to be sorted according to \p sort_function
|
||||||
|
* @param selector LayerSelector instance
|
||||||
|
* @param sort_function The sorting method (up or down sorting)
|
||||||
|
*/
|
||||||
|
void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __LAYER_SELECTOR_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
@@ -27,24 +27,13 @@
|
|||||||
#define __MAPPING_PARSER_H__
|
#define __MAPPING_PARSER_H__
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup Mapping-Parser
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <glib.h>
|
||||||
|
|
||||||
/**
|
#include <gds-render/widgets/layer-element.h>
|
||||||
* @brief Layer information.
|
|
||||||
*
|
|
||||||
* This structs contains information on how to render a layer
|
|
||||||
*/
|
|
||||||
struct layer_info
|
|
||||||
{
|
|
||||||
int layer; /**< @brief Layer number */
|
|
||||||
char *name; /**< @brief Layer name */
|
|
||||||
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
|
||||||
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load a line from \p stream and parse try to parse it as layer information
|
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||||
@@ -55,7 +44,15 @@ struct layer_info
|
|||||||
* @param color RGBA color.
|
* @param color RGBA color.
|
||||||
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
||||||
*/
|
*/
|
||||||
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
|
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create Line for LayerMapping file with supplied information
|
||||||
|
* @param layer_element information
|
||||||
|
* @param line_buffer buffer to write to
|
||||||
|
* @param max_len Maximum length that cna be used in \p line_buffer
|
||||||
|
*/
|
||||||
|
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
@@ -17,6 +17,17 @@
|
|||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file lib-cell-renderer.h
|
||||||
|
* @brief Header file for the LibCellRenderer GObject Class
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup LibCellRenderer
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef __LIB_CELL_RENDERER_H__
|
#ifndef __LIB_CELL_RENDERER_H__
|
||||||
#define __LIB_CELL_RENDERER_H__
|
#define __LIB_CELL_RENDERER_H__
|
||||||
|
|
||||||
@@ -27,8 +38,12 @@ G_BEGIN_DECLS
|
|||||||
G_DECLARE_FINAL_TYPE(LibCellRenderer, lib_cell_renderer, LIB_CELL, RENDERER, GtkCellRendererText)
|
G_DECLARE_FINAL_TYPE(LibCellRenderer, lib_cell_renderer, LIB_CELL, RENDERER, GtkCellRendererText)
|
||||||
#define TYPE_LIB_CELL_RENDERER (lib_cell_renderer_get_type())
|
#define TYPE_LIB_CELL_RENDERER (lib_cell_renderer_get_type())
|
||||||
|
|
||||||
|
/** @{
|
||||||
|
* Error levels
|
||||||
|
*/
|
||||||
#define LIB_CELL_RENDERER_ERROR_WARN (1U<<0)
|
#define LIB_CELL_RENDERER_ERROR_WARN (1U<<0)
|
||||||
#define LIB_CELL_RENDERER_ERROR_ERR (1U<<1)
|
#define LIB_CELL_RENDERER_ERROR_ERR (1U<<1)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
typedef struct _LibCellRenderer {
|
typedef struct _LibCellRenderer {
|
||||||
/* Inheritance */
|
/* Inheritance */
|
||||||
@@ -36,9 +51,20 @@ typedef struct _LibCellRenderer {
|
|||||||
/* Custom Elements */
|
/* Custom Elements */
|
||||||
} LibCellRenderer;
|
} LibCellRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief lib_cell_renderer_get_type
|
||||||
|
* @return GObject Type
|
||||||
|
*/
|
||||||
GType lib_cell_renderer_get_type(void);
|
GType lib_cell_renderer_get_type(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new renderer for renderering @ref gds_cell and @ref gds_library elements.
|
||||||
|
* @return New renderer object
|
||||||
|
*/
|
||||||
GtkCellRenderer *lib_cell_renderer_new(void);
|
GtkCellRenderer *lib_cell_renderer_new(void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __LIB_CELL_RENDERER_H__ */
|
#endif /* __LIB_CELL_RENDERER_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup GUI
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
@@ -18,11 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup version
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @brief This string holds the 'git describe' version of the app */
|
/** @brief This string holds the @ref git-version-num of the app */
|
||||||
extern char *_app_version_string;
|
extern const char *_app_version_string;
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
@@ -24,7 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Widgets
|
* @addtogroup RendererSettingsDialog
|
||||||
|
* @ingroup Widgets
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
@@ -24,7 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Widgets
|
* @addtogroup LayerElement
|
||||||
|
* @ingroup Widgets
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -56,6 +57,22 @@ struct _LayerElement {
|
|||||||
LayerElementPriv priv;
|
LayerElementPriv priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This structure holds the necessary data to set up a LayerElement for Drag'n'Drop
|
||||||
|
*/
|
||||||
|
struct layer_element_dnd_data {
|
||||||
|
/** @brief Array of target entries for the DnD operation */
|
||||||
|
GtkTargetEntry *entries;
|
||||||
|
/** @brief Count of elements in layer_element_dnd_data::entries array */
|
||||||
|
int entry_count;
|
||||||
|
/** @brief Callback function for drag_begin event */
|
||||||
|
void (*drag_begin)(GtkWidget *, GdkDragContext *, gpointer);
|
||||||
|
/** @brief Callback fucktion for data_get event */
|
||||||
|
void (*drag_data_get)(GtkWidget *, GdkDragContext *, GtkSelectionData *, guint, guint, gpointer);
|
||||||
|
/** @brief Callback function for drag_end event */
|
||||||
|
void (*drag_end)(GtkWidget *, GdkDragContext *, gpointer);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create new layer element object
|
* @brief Create new layer element object
|
||||||
* @return new object
|
* @return new object
|
||||||
@@ -118,6 +135,13 @@ void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba);
|
|||||||
*/
|
*/
|
||||||
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
|
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup drag and drop of \p elem for use in the LayerSelector
|
||||||
|
* @param elem Layer element to set up
|
||||||
|
* @param data Data array containing the necessary callbacks etc. for drag and drop.
|
||||||
|
*/
|
||||||
|
void layer_element_set_dnd_callbacks(LayerElement *elem, struct layer_element_dnd_data *data);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __LAYER_ELEMENT_H__ */
|
#endif /* __LAYER_ELEMENT_H__ */
|
@@ -23,9 +23,10 @@
|
|||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "latex-output.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <gds-render/latex-renderer/latex-output.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup LaTeX-Renderer
|
* @addtogroup LaTeX-Renderer
|
||||||
* @{
|
* @{
|
@@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* GDSII-Converter
|
|
||||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*
|
|
||||||
* This file is part of GDSII-Converter.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Original Drag and Drop Code taken from:
|
|
||||||
* https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/tests/testlist3.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file layer-selector-dnd.c
|
|
||||||
* @brief This file implements the drag and drop functions regarding the list box containing the layer elements
|
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "layer-selector-dnd.h"
|
|
||||||
|
|
||||||
static GtkTargetEntry entries[] = {
|
|
||||||
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GtkListBoxRow *row;
|
|
||||||
|
|
||||||
row = NULL;
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
GtkListBoxRow *tmp;
|
|
||||||
tmp = gtk_list_box_get_row_at_index(list, i);
|
|
||||||
if (tmp == NULL)
|
|
||||||
break;
|
|
||||||
row = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static GtkListBoxRow *layer_selector_get_row_before (GtkListBox *list, GtkListBoxRow *row)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
pos = gtk_list_box_row_get_index (row);
|
|
||||||
return gtk_list_box_get_row_at_index (list, pos - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GtkListBoxRow *layer_selector_get_row_after (GtkListBox *list, GtkListBoxRow *row)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
pos = gtk_list_box_row_get_index(row);
|
|
||||||
return gtk_list_box_get_row_at_index(list, pos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_selector_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
|
||||||
GtkSelectionData *selection_data, guint info, guint32 time,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *row_before, *row_after;
|
|
||||||
GtkWidget *row;
|
|
||||||
GtkWidget *source;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
|
||||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
|
||||||
|
|
||||||
g_object_set_data(G_OBJECT(widget), "row-before", NULL);
|
|
||||||
g_object_set_data(G_OBJECT(widget), "row-after", NULL);
|
|
||||||
|
|
||||||
if (row_before)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
|
||||||
if (row_after)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
|
||||||
|
|
||||||
row = (gpointer) *((gpointer *)gtk_selection_data_get_data(selection_data));
|
|
||||||
source = gtk_widget_get_ancestor(row, GTK_TYPE_LIST_BOX_ROW);
|
|
||||||
|
|
||||||
if (source == row_after)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_object_ref(source);
|
|
||||||
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(source)), source);
|
|
||||||
|
|
||||||
if (row_after)
|
|
||||||
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_after));
|
|
||||||
else
|
|
||||||
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_before)) + 1;
|
|
||||||
|
|
||||||
gtk_list_box_insert(GTK_LIST_BOX(widget), source, pos);
|
|
||||||
g_object_unref(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean layer_selector_drag_motion(GtkWidget *widget, GdkDragContext *context, int x, int y, guint time)
|
|
||||||
{
|
|
||||||
GtkAllocation alloc;
|
|
||||||
GtkWidget *row;
|
|
||||||
int hover_row_y;
|
|
||||||
int hover_row_height;
|
|
||||||
GtkWidget *drag_row;
|
|
||||||
GtkWidget *row_before;
|
|
||||||
GtkWidget *row_after;
|
|
||||||
|
|
||||||
row = GTK_WIDGET(gtk_list_box_get_row_at_y(GTK_LIST_BOX(widget), y));
|
|
||||||
|
|
||||||
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
|
||||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
|
||||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
|
||||||
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
|
||||||
if (row_before)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
|
||||||
if (row_after)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
|
||||||
|
|
||||||
if (row) {
|
|
||||||
gtk_widget_get_allocation(row, &alloc);
|
|
||||||
hover_row_y = alloc.y;
|
|
||||||
hover_row_height = alloc.height;
|
|
||||||
|
|
||||||
if (y < hover_row_y + hover_row_height/2) {
|
|
||||||
row_after = row;
|
|
||||||
row_before = GTK_WIDGET(layer_selector_get_row_before(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
|
|
||||||
} else {
|
|
||||||
row_before = row;
|
|
||||||
row_after = GTK_WIDGET(layer_selector_get_row_after(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
row_before = GTK_WIDGET(layer_selector_get_last_row(GTK_LIST_BOX(widget)));
|
|
||||||
row_after = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_set_data(G_OBJECT(widget), "row-before", row_before);
|
|
||||||
g_object_set_data(G_OBJECT(widget), "row-after", row_after);
|
|
||||||
|
|
||||||
if (drag_row == row_before || drag_row == row_after) {
|
|
||||||
gtk_style_context_add_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row_before)
|
|
||||||
gtk_style_context_add_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
|
||||||
if (row_after)
|
|
||||||
gtk_style_context_add_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_selector_drag_leave(GtkWidget *widget, GdkDragContext *context, guint time)
|
|
||||||
{
|
|
||||||
GtkWidget *drag_row;
|
|
||||||
GtkWidget *row_before;
|
|
||||||
GtkWidget *row_after;
|
|
||||||
|
|
||||||
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
|
||||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
|
||||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
|
||||||
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
|
||||||
if (row_before)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
|
||||||
if (row_after)
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *dnd_additional_css =
|
|
||||||
".row:not(:first-child) { "
|
|
||||||
" border-top: 1px solid alpha(gray,0.5); "
|
|
||||||
" border-bottom: 1px solid transparent; "
|
|
||||||
"}"
|
|
||||||
".row:first-child { "
|
|
||||||
" border-top: 1px solid transparent; "
|
|
||||||
" border-bottom: 1px solid transparent; "
|
|
||||||
"}"
|
|
||||||
".row:last-child { "
|
|
||||||
" border-top: 1px solid alpha(gray,0.5); "
|
|
||||||
" border-bottom: 1px solid alpha(gray,0.5); "
|
|
||||||
"}"
|
|
||||||
".row.drag-icon { "
|
|
||||||
" background: #282828; "
|
|
||||||
" border: 1px solid blue; "
|
|
||||||
"}"
|
|
||||||
".row.drag-row { "
|
|
||||||
" color: gray; "
|
|
||||||
" background: alpha(gray,0.2); "
|
|
||||||
"}"
|
|
||||||
".row.drag-row.drag-hover { "
|
|
||||||
" border-top: 1px solid #4e9a06; "
|
|
||||||
" border-bottom: 1px solid #4e9a06; "
|
|
||||||
"}"
|
|
||||||
".row.drag-hover image, "
|
|
||||||
".row.drag-hover label { "
|
|
||||||
" color: #4e9a06; "
|
|
||||||
"}"
|
|
||||||
".row.drag-hover-top {"
|
|
||||||
" border-top: 1px solid #4e9a06; "
|
|
||||||
"}"
|
|
||||||
".row.drag-hover-bottom {"
|
|
||||||
" border-bottom: 1px solid #4e9a06; "
|
|
||||||
"}";
|
|
||||||
|
|
||||||
void layer_selector_list_box_setup_dnd(GtkListBox *box)
|
|
||||||
{
|
|
||||||
GtkCssProvider *provider;
|
|
||||||
|
|
||||||
provider = gtk_css_provider_new ();
|
|
||||||
gtk_css_provider_load_from_data (provider, dnd_additional_css, -1, NULL);
|
|
||||||
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (provider), 800);
|
|
||||||
|
|
||||||
gtk_drag_dest_set(GTK_WIDGET(box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, entries, 1, GDK_ACTION_MOVE);
|
|
||||||
g_signal_connect(box, "drag-data-received", G_CALLBACK(layer_selector_drag_data_received), NULL);
|
|
||||||
g_signal_connect(box, "drag-motion", G_CALLBACK(layer_selector_drag_motion), NULL);
|
|
||||||
g_signal_connect(box, "drag-leave", G_CALLBACK(layer_selector_drag_leave), NULL);
|
|
||||||
|
|
||||||
}
|
|
@@ -1,456 +0,0 @@
|
|||||||
/*
|
|
||||||
* GDSII-Converter
|
|
||||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*
|
|
||||||
* This file is part of GDSII-Converter.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file layer-selector.c
|
|
||||||
* @brief Implementation of the layer selector
|
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @addtogroup MainApplication
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "layer-selector.h"
|
|
||||||
#include "../gds-parser/gds-parser.h"
|
|
||||||
#include "../widgets/layer-element.h"
|
|
||||||
#include <glib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static GtkWidget *global_load_button;
|
|
||||||
static GtkWidget *global_save_button;
|
|
||||||
static GtkListBox *global_list_box;
|
|
||||||
|
|
||||||
void delete_layer_info_struct(struct layer_info *info)
|
|
||||||
{
|
|
||||||
if (info)
|
|
||||||
free(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief export_rendered_layer_info
|
|
||||||
* @return new list with all info elements needed to render cells
|
|
||||||
*/
|
|
||||||
GList *export_rendered_layer_info()
|
|
||||||
{
|
|
||||||
GList *info_list = NULL;
|
|
||||||
LayerElement *le;
|
|
||||||
struct layer_info *linfo;
|
|
||||||
GList *row_list;
|
|
||||||
GList *temp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
row_list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
|
|
||||||
|
|
||||||
/* Iterate through widgets and add layers that shall be exported */
|
|
||||||
for (i = 0, temp = row_list; temp != NULL; temp = temp->next, i++) {
|
|
||||||
|
|
||||||
le = LAYER_ELEMENT(temp->data);
|
|
||||||
|
|
||||||
if (layer_element_get_export(le) == TRUE) {
|
|
||||||
/* Allocate new info and fill with info */
|
|
||||||
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
|
|
||||||
layer_element_get_color(le, &linfo->color);
|
|
||||||
linfo->layer = layer_element_get_layer(le);
|
|
||||||
linfo->stacked_position = i;
|
|
||||||
linfo->name = (char *)layer_element_get_name(le);
|
|
||||||
|
|
||||||
/* Append to list */
|
|
||||||
info_list = g_list_append(info_list, (gpointer)linfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return info_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_list_box_widgets(GtkListBox *box)
|
|
||||||
{
|
|
||||||
GList *list;
|
|
||||||
GList *temp;
|
|
||||||
|
|
||||||
list = gtk_container_get_children(GTK_CONTAINER(box));
|
|
||||||
for (temp = list; temp != NULL; temp = temp->next) {
|
|
||||||
gtk_container_remove(GTK_CONTAINER(box), GTK_WIDGET(temp->data));
|
|
||||||
}
|
|
||||||
/* Widgets are already destroyed when removed from box because they are only referenced inside the container */
|
|
||||||
|
|
||||||
g_list_free(list);
|
|
||||||
|
|
||||||
/* Deactivate buttons */
|
|
||||||
gtk_widget_set_sensitive(global_load_button, FALSE);
|
|
||||||
gtk_widget_set_sensitive(global_save_button, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if specific layer number is present in list box
|
|
||||||
* @param layer Layer nu,ber
|
|
||||||
* @return TRUE if present
|
|
||||||
*/
|
|
||||||
static gboolean check_if_layer_widget_exists(int layer) {
|
|
||||||
GList *list;
|
|
||||||
GList *temp;
|
|
||||||
LayerElement *widget;
|
|
||||||
gboolean ret = FALSE;
|
|
||||||
|
|
||||||
list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
|
|
||||||
|
|
||||||
for (temp = list; temp != NULL; temp = temp->next) {
|
|
||||||
widget = LAYER_ELEMENT(temp->data);
|
|
||||||
if (layer_element_get_layer(widget) == layer) {
|
|
||||||
ret = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free(list);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Analyze \p cell and append used layers to list box
|
|
||||||
* @param listbox listbox to add layer
|
|
||||||
* @param cell Cell to analyze
|
|
||||||
*/
|
|
||||||
static void analyze_cell_layers(GtkListBox *listbox, struct gds_cell *cell)
|
|
||||||
{
|
|
||||||
GList *graphics;
|
|
||||||
struct gds_graphics *gfx;
|
|
||||||
int layer;
|
|
||||||
GtkWidget *le;
|
|
||||||
|
|
||||||
for (graphics = cell->graphic_objs; graphics != NULL; graphics = graphics->next) {
|
|
||||||
gfx = (struct gds_graphics *)graphics->data;
|
|
||||||
layer = (int)gfx->layer;
|
|
||||||
if (check_if_layer_widget_exists(layer) == FALSE) {
|
|
||||||
le = layer_element_new();
|
|
||||||
layer_element_set_layer(LAYER_ELEMENT(le), layer);
|
|
||||||
gtk_list_box_insert(listbox, le, -1);
|
|
||||||
gtk_widget_show(le);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief sort_func Sort callback for list box
|
|
||||||
* @param row1
|
|
||||||
* @param row2
|
|
||||||
* @param unused
|
|
||||||
* @note Do not use this function. This is an internal callback
|
|
||||||
* @return See sort function documentation of GTK+
|
|
||||||
*/
|
|
||||||
static gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
|
||||||
{
|
|
||||||
LayerElement *le1, *le2;
|
|
||||||
gint ret;
|
|
||||||
static const enum layer_selector_sort_algo default_sort = LAYER_SELECTOR_SORT_DOWN;
|
|
||||||
const enum layer_selector_sort_algo *algo = (const enum layer_selector_sort_algo *)unused;
|
|
||||||
|
|
||||||
/* Assume downward sorting */
|
|
||||||
/* TODO: This is nasty. Find a better way */
|
|
||||||
if (!algo)
|
|
||||||
algo = &default_sort;
|
|
||||||
|
|
||||||
le1 = LAYER_ELEMENT(row1);
|
|
||||||
le2 = LAYER_ELEMENT(row2);
|
|
||||||
|
|
||||||
/* Determine sort fow downward sort */
|
|
||||||
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
|
|
||||||
|
|
||||||
/* Change order if upward sort is requested */
|
|
||||||
ret *= (*algo == LAYER_SELECTOR_SORT_DOWN ? 1 : -1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
|
||||||
{
|
|
||||||
GList *cell_list = NULL;
|
|
||||||
struct gds_library *lib;
|
|
||||||
|
|
||||||
global_list_box = listbox;
|
|
||||||
|
|
||||||
clear_list_box_widgets(listbox);
|
|
||||||
|
|
||||||
for (; libs != NULL; libs = libs->next) {
|
|
||||||
lib = (struct gds_library *)libs->data;
|
|
||||||
for (cell_list = lib->cells; cell_list != NULL; cell_list = cell_list->next) {
|
|
||||||
analyze_cell_layers(listbox, (struct gds_cell *)cell_list->data);
|
|
||||||
} /* For Cell List */
|
|
||||||
} /* For libs */
|
|
||||||
|
|
||||||
/* Sort the layers */
|
|
||||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_DOWN);
|
|
||||||
|
|
||||||
/* Activate Buttons */
|
|
||||||
gtk_widget_set_sensitive(global_load_button, TRUE);
|
|
||||||
gtk_widget_set_sensitive(global_save_button, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Find LayerElement in list with specified layer number
|
|
||||||
* @param el_list List with elements of type LayerElement
|
|
||||||
* @param layer Layer number
|
|
||||||
* @return Found LayerElement. If nothing is found, NULL.
|
|
||||||
*/
|
|
||||||
static LayerElement *find_layer_element_in_list(GList *el_list, int layer)
|
|
||||||
{
|
|
||||||
LayerElement *ret = NULL;
|
|
||||||
for (; el_list != NULL; el_list = el_list->next) {
|
|
||||||
if (layer_element_get_layer(LAYER_ELEMENT(el_list->data)) == layer) {
|
|
||||||
ret = LAYER_ELEMENT(el_list->data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load file and apply layer definitions to listbox
|
|
||||||
* @param file_name CSV Layer Mapping File
|
|
||||||
*/
|
|
||||||
static void load_layer_mapping_from_file(gchar *file_name)
|
|
||||||
{
|
|
||||||
GFile *file;
|
|
||||||
GFileInputStream *stream;
|
|
||||||
GDataInputStream *dstream;
|
|
||||||
LayerElement *le;
|
|
||||||
char *name;
|
|
||||||
gboolean export;
|
|
||||||
int layer;
|
|
||||||
GdkRGBA color;
|
|
||||||
int result;
|
|
||||||
GList *rows;
|
|
||||||
GList *temp;
|
|
||||||
|
|
||||||
file = g_file_new_for_path(file_name);
|
|
||||||
stream = g_file_read(file, NULL, NULL);
|
|
||||||
|
|
||||||
if (!stream)
|
|
||||||
goto destroy_file;
|
|
||||||
|
|
||||||
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
|
||||||
|
|
||||||
rows = gtk_container_get_children(GTK_CONTAINER(global_list_box));
|
|
||||||
|
|
||||||
/* Reference and remove all rows from box */
|
|
||||||
for (temp = rows; temp != NULL; temp = temp->next) {
|
|
||||||
le = LAYER_ELEMENT(temp->data);
|
|
||||||
/* Referencing protets the widget from being deleted when removed */
|
|
||||||
g_object_ref(G_OBJECT(le));
|
|
||||||
gtk_container_remove(GTK_CONTAINER(global_list_box), GTK_WIDGET(le));
|
|
||||||
}
|
|
||||||
|
|
||||||
while((result = load_csv_line(dstream, &export, &name, &layer, &color)) >= 0) {
|
|
||||||
/* skip broken line */
|
|
||||||
if (result == 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add rows in the same order as in file */
|
|
||||||
if ((le = find_layer_element_in_list(rows, layer))) {
|
|
||||||
gtk_list_box_insert(global_list_box, GTK_WIDGET(le), -1);
|
|
||||||
|
|
||||||
layer_element_set_color(le, &color);
|
|
||||||
layer_element_set_export(le, export);
|
|
||||||
layer_element_set_name(le, name);
|
|
||||||
g_free(name);
|
|
||||||
|
|
||||||
/* Dereference and remove from list */
|
|
||||||
g_object_unref(G_OBJECT(le));
|
|
||||||
rows = g_list_remove(rows, le);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add remaining elements */
|
|
||||||
for (temp = rows; temp != NULL; temp = temp->next) {
|
|
||||||
le = LAYER_ELEMENT(temp->data);
|
|
||||||
/* Referencing protets the widget from being deleted when removed */
|
|
||||||
gtk_list_box_insert(global_list_box, GTK_WIDGET(le), -1);
|
|
||||||
g_object_unref(G_OBJECT(le));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete list */
|
|
||||||
g_list_free(rows);
|
|
||||||
|
|
||||||
/* read line */
|
|
||||||
g_object_unref(dstream);
|
|
||||||
g_object_unref(stream);
|
|
||||||
destroy_file:
|
|
||||||
g_object_unref(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback for Load Mapping Button
|
|
||||||
* @param button
|
|
||||||
* @param user_data
|
|
||||||
*/
|
|
||||||
static void load_mapping_clicked(GtkWidget *button, gpointer user_data)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
gint res;
|
|
||||||
gchar *file_name;
|
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new("Load Mapping File", GTK_WINDOW(user_data), GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
||||||
"Cancel", GTK_RESPONSE_CANCEL, "Load Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
|
||||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
|
||||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
load_layer_mapping_from_file(file_name);
|
|
||||||
g_free(file_name);
|
|
||||||
}
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create Line for LayerMapping file with supplied information
|
|
||||||
* @param layer_element information
|
|
||||||
* @param line_buffer buffer to write to
|
|
||||||
* @param max_len Maximum length that cna be used in \p line_buffer
|
|
||||||
*/
|
|
||||||
static void create_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GString *string;
|
|
||||||
gboolean export;
|
|
||||||
const gchar *name;
|
|
||||||
int layer;
|
|
||||||
GdkRGBA color;
|
|
||||||
|
|
||||||
string = g_string_new_len(NULL, max_len-1);
|
|
||||||
|
|
||||||
/* Extract values */
|
|
||||||
export = layer_element_get_export(layer_element);
|
|
||||||
name = (const gchar*)layer_element_get_name(layer_element);
|
|
||||||
layer = layer_element_get_layer(layer_element);
|
|
||||||
layer_element_get_color(layer_element, &color);
|
|
||||||
|
|
||||||
/* print values to line */
|
|
||||||
g_string_printf(string, "%d:%lf:%lf:%lf:%lf:%d:%s\n",
|
|
||||||
layer, color.red, color.green,
|
|
||||||
color.blue, color.alpha, (export == TRUE ? 1 : 0), name);
|
|
||||||
/* Fix broken locale settings */
|
|
||||||
for (i = 0; string->str[i]; i++) {
|
|
||||||
if (string->str[i] == ',')
|
|
||||||
string->str[i] = '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; string->str[i]; i++) {
|
|
||||||
if (string->str[i] == ':')
|
|
||||||
string->str[i] = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string->len > (max_len-1)) {
|
|
||||||
printf("Layer Definition too long. Please shorten Layer Name!!\n");
|
|
||||||
line_buffer[0] = 0x0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy max_len bytes of string */
|
|
||||||
strncpy(line_buffer, (char *)string->str, max_len-1);
|
|
||||||
line_buffer[max_len-1] = 0;
|
|
||||||
|
|
||||||
/* Completely remove string */
|
|
||||||
g_string_free(string, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Save layer mapping of whole list box into file
|
|
||||||
* @param file_name layer mapping file
|
|
||||||
* @param list_box listbox
|
|
||||||
*/
|
|
||||||
static void save_layer_mapping_data(const gchar *file_name, GtkListBox *list_box)
|
|
||||||
{
|
|
||||||
FILE *file;
|
|
||||||
char workbuff[512];
|
|
||||||
GList *le_list;
|
|
||||||
GList *temp;
|
|
||||||
|
|
||||||
/* Overwrite existing file */
|
|
||||||
file = fopen((const char *)file_name, "w");
|
|
||||||
|
|
||||||
le_list = gtk_container_get_children(GTK_CONTAINER(list_box));
|
|
||||||
|
|
||||||
/* File format is CSV: <Layer>,<target_pos>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
|
|
||||||
for (temp = le_list; temp != NULL; temp = temp->next) {
|
|
||||||
/* To be sure it is a valid string */
|
|
||||||
workbuff[0] = 0;
|
|
||||||
create_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
|
|
||||||
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free(le_list);
|
|
||||||
|
|
||||||
/* Save File */
|
|
||||||
fflush(file);
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback for Save Layer Mapping Button
|
|
||||||
* @param button
|
|
||||||
* @param user_data
|
|
||||||
*/
|
|
||||||
static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
gint res;
|
|
||||||
gchar *file_name;
|
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(user_data), GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
"Cancel", GTK_RESPONSE_CANCEL, "Save Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
|
|
||||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
|
||||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
save_layer_mapping_data(file_name, global_list_box);
|
|
||||||
g_free(file_name);
|
|
||||||
}
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
|
||||||
{
|
|
||||||
g_object_ref(G_OBJECT(button));
|
|
||||||
global_load_button = button;
|
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(load_mapping_clicked), main_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
|
||||||
{
|
|
||||||
g_object_ref(G_OBJECT(button));
|
|
||||||
global_save_button = button;
|
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(save_mapping_clicked), main_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_selector_force_sort(enum layer_selector_sort_algo sort_function)
|
|
||||||
{
|
|
||||||
if (!global_list_box)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Set dorting function, sort, and disable sorting function */
|
|
||||||
gtk_list_box_set_sort_func(global_list_box, sort_func, (gpointer)&sort_function, NULL);
|
|
||||||
gtk_list_box_invalidate_sort(global_list_box);
|
|
||||||
gtk_list_box_set_sort_func(global_list_box, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* GDSII-Converter
|
|
||||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*
|
|
||||||
* This file is part of GDSII-Converter.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file layer-selector.h
|
|
||||||
* @brief Implementation of the Layer selection list
|
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LAYER_SELECTOR_H__
|
|
||||||
#define __LAYER_SELECTOR_H__
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include "../mapping-parser.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Defines how to sort the layer selector list box.
|
|
||||||
*/
|
|
||||||
enum layer_selector_sort_algo {LAYER_SELECTOR_SORT_DOWN = 0, LAYER_SELECTOR_SORT_UP};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate layer widgets in \p listbox
|
|
||||||
* @note This clears all previously inserted elements
|
|
||||||
* @param listbox
|
|
||||||
* @param libs The library to add
|
|
||||||
*/
|
|
||||||
void generate_layer_widgets(GtkListBox *listbox, GList *libs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Supply button for loading the layer mapping
|
|
||||||
* @param button
|
|
||||||
* @param main_window Parent window for dialogs
|
|
||||||
*/
|
|
||||||
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Supply button for saving the layer mapping
|
|
||||||
* @param button
|
|
||||||
* @param main_window
|
|
||||||
*/
|
|
||||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief get the layer information present in the listbox of the selector
|
|
||||||
* @return List with layer_info elements
|
|
||||||
*/
|
|
||||||
GList *export_rendered_layer_info();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete a layer_info struct
|
|
||||||
* @param info Struct to be deleted.
|
|
||||||
* @note The layer_info::name Element has to be freed manually
|
|
||||||
*/
|
|
||||||
void delete_layer_info_struct(struct layer_info *info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Force sorting of the layer selector in a specified way
|
|
||||||
*
|
|
||||||
* If the layer selector is not yet set up, this function has no effect.
|
|
||||||
*
|
|
||||||
* @param sort_function Sorting direction
|
|
||||||
*/
|
|
||||||
void layer_selector_force_sort(enum layer_selector_sort_algo sort_function);
|
|
||||||
|
|
||||||
#endif /* __LAYER_SELECTOR_H__ */
|
|
@@ -18,16 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file layer-selector-dnd.h
|
* @file layer-info.c
|
||||||
* @brief Header for drag and drop of layer selector
|
* @brief Helper functions for layer info struct
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LAYER_SELECTOR_DND_H_
|
#include <gds-render/layer/layer-info.h>
|
||||||
#define _LAYER_SELECTOR_DND_H_
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
void layer_info_delete_struct(struct layer_info *info)
|
||||||
|
{
|
||||||
|
if (info)
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
void layer_selector_list_box_setup_dnd(GtkListBox *box);
|
|
||||||
|
|
||||||
#endif /* _LAYER_SELECTOR_DND_H_ */
|
|
784
layer/layer-selector.c
Normal file
784
layer/layer-selector.c
Normal file
@@ -0,0 +1,784 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file layer-selector.c
|
||||||
|
* @brief Implementation of the layer selector
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup layer-selector
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <gds-render/layer/layer-selector.h>
|
||||||
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
#include <gds-render/gds-utils/gds-parser.h>
|
||||||
|
#include <gds-render/widgets/layer-element.h>
|
||||||
|
#include <gds-render/layer/mapping-parser.h>
|
||||||
|
|
||||||
|
struct _LayerSelector {
|
||||||
|
/* Parent */
|
||||||
|
GObject parent;
|
||||||
|
/* Own fields */
|
||||||
|
GtkWidget *associated_load_button;
|
||||||
|
GtkWidget *associated_save_button;
|
||||||
|
GtkWindow *load_parent_window;
|
||||||
|
GtkWindow *save_parent_window;
|
||||||
|
GtkListBox *list_box;
|
||||||
|
|
||||||
|
GtkTargetEntry dnd_target;
|
||||||
|
|
||||||
|
gpointer dummy[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(LayerSelector, layer_selector, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
/* Drag and drop code
|
||||||
|
* Original code from https://blog.gtk.org/2017/06/01/drag-and-drop-in-lists-revisited/
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void sel_layer_element_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *row;
|
||||||
|
GtkAllocation alloc;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
int x, y;
|
||||||
|
(void)data;
|
||||||
|
|
||||||
|
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
|
||||||
|
gtk_widget_get_allocation(row, &alloc);
|
||||||
|
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
|
||||||
|
cr = cairo_create(surface);
|
||||||
|
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context(row), "drag-icon");
|
||||||
|
gtk_widget_draw (row, cr);
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-icon");
|
||||||
|
|
||||||
|
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
|
||||||
|
cairo_surface_set_device_offset (surface, -x, -y);
|
||||||
|
gtk_drag_set_icon_surface (context, surface);
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
|
||||||
|
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sel_layer_element_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *row;
|
||||||
|
(void)context;
|
||||||
|
(void)data;
|
||||||
|
|
||||||
|
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
|
||||||
|
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL);
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-row");
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-hover");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sel_layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *context,
|
||||||
|
GtkSelectionData *selection_data,
|
||||||
|
guint info, guint time, gpointer data)
|
||||||
|
{
|
||||||
|
(void)context;
|
||||||
|
(void)info;
|
||||||
|
(void)time;
|
||||||
|
(void)data;
|
||||||
|
GdkAtom atom;
|
||||||
|
|
||||||
|
atom = gdk_atom_intern_static_string("GTK_LIST_BOX_ROW");
|
||||||
|
|
||||||
|
gtk_selection_data_set(selection_data, atom,
|
||||||
|
32, (const guchar *)&widget, sizeof(gpointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GtkListBoxRow *row;
|
||||||
|
|
||||||
|
row = NULL;
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
GtkListBoxRow *tmp;
|
||||||
|
tmp = gtk_list_box_get_row_at_index(list, i);
|
||||||
|
if (tmp == NULL)
|
||||||
|
break;
|
||||||
|
row = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkListBoxRow *layer_selector_get_row_before (GtkListBox *list, GtkListBoxRow *row)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = gtk_list_box_row_get_index (row);
|
||||||
|
return gtk_list_box_get_row_at_index (list, pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkListBoxRow *layer_selector_get_row_after (GtkListBox *list, GtkListBoxRow *row)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = gtk_list_box_row_get_index(row);
|
||||||
|
return gtk_list_box_get_row_at_index(list, pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_selector_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
||||||
|
GtkSelectionData *selection_data, guint info, guint32 time,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *row_before, *row_after;
|
||||||
|
GtkWidget *row;
|
||||||
|
GtkWidget *source;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||||
|
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||||
|
|
||||||
|
g_object_set_data(G_OBJECT(widget), "row-before", NULL);
|
||||||
|
g_object_set_data(G_OBJECT(widget), "row-after", NULL);
|
||||||
|
|
||||||
|
if (row_before)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||||
|
if (row_after)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||||
|
|
||||||
|
row = (gpointer) *((gpointer *)gtk_selection_data_get_data(selection_data));
|
||||||
|
source = gtk_widget_get_ancestor(row, GTK_TYPE_LIST_BOX_ROW);
|
||||||
|
|
||||||
|
if (source == row_after)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_ref(source);
|
||||||
|
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(source)), source);
|
||||||
|
|
||||||
|
if (row_after)
|
||||||
|
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_after));
|
||||||
|
else
|
||||||
|
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_before)) + 1;
|
||||||
|
|
||||||
|
gtk_list_box_insert(GTK_LIST_BOX(widget), source, pos);
|
||||||
|
g_object_unref(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean layer_selector_drag_motion(GtkWidget *widget, GdkDragContext *context, int x, int y, guint time)
|
||||||
|
{
|
||||||
|
GtkAllocation alloc;
|
||||||
|
GtkWidget *row;
|
||||||
|
int hover_row_y;
|
||||||
|
int hover_row_height;
|
||||||
|
GtkWidget *drag_row;
|
||||||
|
GtkWidget *row_before;
|
||||||
|
GtkWidget *row_after;
|
||||||
|
|
||||||
|
row = GTK_WIDGET(gtk_list_box_get_row_at_y(GTK_LIST_BOX(widget), y));
|
||||||
|
|
||||||
|
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
||||||
|
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||||
|
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||||
|
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||||
|
if (row_before)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||||
|
if (row_after)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||||
|
|
||||||
|
if (row) {
|
||||||
|
gtk_widget_get_allocation(row, &alloc);
|
||||||
|
hover_row_y = alloc.y;
|
||||||
|
hover_row_height = alloc.height;
|
||||||
|
|
||||||
|
if (y < hover_row_y + hover_row_height/2) {
|
||||||
|
row_after = row;
|
||||||
|
row_before = GTK_WIDGET(layer_selector_get_row_before(GTK_LIST_BOX(widget),
|
||||||
|
GTK_LIST_BOX_ROW(row)));
|
||||||
|
} else {
|
||||||
|
row_before = row;
|
||||||
|
row_after = GTK_WIDGET(layer_selector_get_row_after(GTK_LIST_BOX(widget),
|
||||||
|
GTK_LIST_BOX_ROW(row)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row_before = GTK_WIDGET(layer_selector_get_last_row(GTK_LIST_BOX(widget)));
|
||||||
|
row_after = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set_data(G_OBJECT(widget), "row-before", row_before);
|
||||||
|
g_object_set_data(G_OBJECT(widget), "row-after", row_after);
|
||||||
|
|
||||||
|
if (drag_row == row_before || drag_row == row_after) {
|
||||||
|
gtk_style_context_add_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row_before)
|
||||||
|
gtk_style_context_add_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||||
|
if (row_after)
|
||||||
|
gtk_style_context_add_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_selector_drag_leave(GtkWidget *widget, GdkDragContext *context, guint time)
|
||||||
|
{
|
||||||
|
GtkWidget *drag_row;
|
||||||
|
GtkWidget *row_before;
|
||||||
|
GtkWidget *row_after;
|
||||||
|
|
||||||
|
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
||||||
|
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||||
|
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||||
|
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||||
|
if (row_before)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||||
|
if (row_after)
|
||||||
|
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *dnd_additional_css =
|
||||||
|
".row:not(:first-child) { "
|
||||||
|
" border-top: 1px solid alpha(gray,0.5); "
|
||||||
|
" border-bottom: 1px solid transparent; "
|
||||||
|
"}"
|
||||||
|
".row:first-child { "
|
||||||
|
" border-top: 1px solid transparent; "
|
||||||
|
" border-bottom: 1px solid transparent; "
|
||||||
|
"}"
|
||||||
|
".row:last-child { "
|
||||||
|
" border-top: 1px solid alpha(gray,0.5); "
|
||||||
|
" border-bottom: 1px solid alpha(gray,0.5); "
|
||||||
|
"}"
|
||||||
|
".row.drag-icon { "
|
||||||
|
" background: #282828; "
|
||||||
|
" border: 1px solid blue; "
|
||||||
|
"}"
|
||||||
|
".row.drag-row { "
|
||||||
|
" color: gray; "
|
||||||
|
" background: alpha(gray,0.2); "
|
||||||
|
"}"
|
||||||
|
".row.drag-row.drag-hover { "
|
||||||
|
" border-top: 1px solid #4e9a06; "
|
||||||
|
" border-bottom: 1px solid #4e9a06; "
|
||||||
|
"}"
|
||||||
|
".row.drag-hover image, "
|
||||||
|
".row.drag-hover label { "
|
||||||
|
" color: #4e9a06; "
|
||||||
|
"}"
|
||||||
|
".row.drag-hover-top {"
|
||||||
|
" border-top: 1px solid #4e9a06; "
|
||||||
|
"}"
|
||||||
|
".row.drag-hover-bottom {"
|
||||||
|
" border-bottom: 1px solid #4e9a06; "
|
||||||
|
"}";
|
||||||
|
|
||||||
|
static void layer_selector_dispose(GObject *self)
|
||||||
|
{
|
||||||
|
LayerSelector *sel = LAYER_SELECTOR(self);
|
||||||
|
|
||||||
|
g_clear_object(&sel->list_box);
|
||||||
|
g_clear_object(&sel->load_parent_window);
|
||||||
|
g_clear_object(&sel->save_parent_window);
|
||||||
|
g_clear_object(&sel->associated_load_button);
|
||||||
|
g_clear_object(&sel->associated_save_button);
|
||||||
|
|
||||||
|
if (sel->dnd_target.target) {
|
||||||
|
g_free(sel->dnd_target.target);
|
||||||
|
sel->dnd_target.target = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chain up to parent's dispose function */
|
||||||
|
G_OBJECT_CLASS(layer_selector_parent_class)->dispose(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_selector_class_init(LayerSelectorClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
GtkCssProvider *provider;
|
||||||
|
|
||||||
|
/* Implement handles to virtual functions */
|
||||||
|
object_class->dispose = layer_selector_dispose;
|
||||||
|
|
||||||
|
/* Setup the CSS provider for the drag and drop animations once */
|
||||||
|
provider = gtk_css_provider_new();
|
||||||
|
gtk_css_provider_load_from_data(provider, dnd_additional_css, -1, NULL);
|
||||||
|
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(provider), 800);
|
||||||
|
|
||||||
|
g_object_unref(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_selector_setup_dnd(LayerSelector *self)
|
||||||
|
{
|
||||||
|
gtk_drag_dest_set(GTK_WIDGET(self->list_box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, &self->dnd_target, 1, GDK_ACTION_MOVE);
|
||||||
|
g_signal_connect(self->list_box, "drag-data-received", G_CALLBACK(layer_selector_drag_data_received), NULL);
|
||||||
|
g_signal_connect(self->list_box, "drag-motion", G_CALLBACK(layer_selector_drag_motion), NULL);
|
||||||
|
g_signal_connect(self->list_box, "drag-leave", G_CALLBACK(layer_selector_drag_leave), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drag and drop end */
|
||||||
|
|
||||||
|
static void layer_selector_init(LayerSelector *self)
|
||||||
|
{
|
||||||
|
self->load_parent_window = NULL;
|
||||||
|
self->save_parent_window = NULL;
|
||||||
|
self->associated_load_button = NULL;
|
||||||
|
self->associated_save_button = NULL;
|
||||||
|
|
||||||
|
self->dnd_target.target = g_strdup_printf("LAYER_SELECTOR_DND_%p", self);
|
||||||
|
self->dnd_target.info = 0;
|
||||||
|
self->dnd_target.flags = GTK_TARGET_SAME_APP;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerSelector *layer_selector_new(GtkListBox *list_box)
|
||||||
|
{
|
||||||
|
LayerSelector *selector;
|
||||||
|
|
||||||
|
if (GTK_IS_LIST_BOX(list_box) == FALSE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
selector = LAYER_SELECTOR(g_object_new(TYPE_LAYER_SELECTOR, NULL));
|
||||||
|
selector->list_box = list_box;
|
||||||
|
layer_selector_setup_dnd(selector);
|
||||||
|
g_object_ref(G_OBJECT(list_box));
|
||||||
|
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *layer_selector_export_rendered_layer_info(LayerSelector *selector)
|
||||||
|
{
|
||||||
|
GList *info_list = NULL;
|
||||||
|
LayerElement *le;
|
||||||
|
struct layer_info *linfo;
|
||||||
|
GList *row_list;
|
||||||
|
GList *temp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!selector)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
row_list = gtk_container_get_children(GTK_CONTAINER(selector->list_box));
|
||||||
|
|
||||||
|
/* Iterate through widgets and add layers that shall be exported */
|
||||||
|
for (i = 0, temp = row_list; temp != NULL; temp = temp->next, i++) {
|
||||||
|
|
||||||
|
le = LAYER_ELEMENT(temp->data);
|
||||||
|
|
||||||
|
if (layer_element_get_export(le) == TRUE) {
|
||||||
|
/* Allocate new info and fill with info */
|
||||||
|
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||||
|
layer_element_get_color(le, &linfo->color);
|
||||||
|
linfo->layer = layer_element_get_layer(le);
|
||||||
|
linfo->stacked_position = i;
|
||||||
|
linfo->name = (char *)layer_element_get_name(le);
|
||||||
|
|
||||||
|
/* Append to list */
|
||||||
|
info_list = g_list_append(info_list, (gpointer)linfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_selector_clear_widgets(LayerSelector *self)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
|
list = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||||
|
for (temp = list; temp != NULL; temp = temp->next) {
|
||||||
|
gtk_container_remove(GTK_CONTAINER(self->list_box), GTK_WIDGET(temp->data));
|
||||||
|
}
|
||||||
|
/* Widgets are already destroyed when removed from box because they are only referenced inside the container */
|
||||||
|
|
||||||
|
g_list_free(list);
|
||||||
|
|
||||||
|
/* Deactivate buttons */
|
||||||
|
if (self->associated_load_button)
|
||||||
|
gtk_widget_set_sensitive(self->associated_load_button, FALSE);
|
||||||
|
if (self->associated_save_button)
|
||||||
|
gtk_widget_set_sensitive(self->associated_save_button, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a specific layer element with the given layer number is present in the layer selector
|
||||||
|
* @param self LayerSelector instance
|
||||||
|
* @param layer Layer number to check for
|
||||||
|
* @return TRUE if layer is present, else FALSE
|
||||||
|
*/
|
||||||
|
static gboolean layer_selector_check_if_layer_widget_exists(LayerSelector *self, int layer) {
|
||||||
|
GList *list;
|
||||||
|
GList *temp;
|
||||||
|
LayerElement *widget;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
list = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||||
|
|
||||||
|
for (temp = list; temp != NULL; temp = temp->next) {
|
||||||
|
widget = LAYER_ELEMENT(temp->data);
|
||||||
|
if (layer_element_get_layer(widget) == layer) {
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(list);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup the necessary drag and drop callbacks of layer elements.
|
||||||
|
* @param self LayerSelector instance. Used to get the DnD target entry.
|
||||||
|
* @param element LayerElement instance to set the callbacks
|
||||||
|
*/
|
||||||
|
static void sel_layer_element_setup_dnd_callbacks(LayerSelector *self, LayerElement *element)
|
||||||
|
{
|
||||||
|
struct layer_element_dnd_data dnd_data;
|
||||||
|
|
||||||
|
if (!self || !element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dnd_data.entries = &self->dnd_target;
|
||||||
|
dnd_data.entry_count = 1;
|
||||||
|
dnd_data.drag_end = sel_layer_element_drag_end;
|
||||||
|
dnd_data.drag_begin = sel_layer_element_drag_begin;
|
||||||
|
dnd_data.drag_data_get = sel_layer_element_drag_data_get;
|
||||||
|
|
||||||
|
layer_element_set_dnd_callbacks(element, &dnd_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Analyze \p cell layers and append detected layers to layer selector \p self
|
||||||
|
* @param self LayerSelector instance
|
||||||
|
* @param cell Cell to analyze
|
||||||
|
*/
|
||||||
|
static void layer_selector_analyze_cell_layers(LayerSelector *self, struct gds_cell *cell)
|
||||||
|
{
|
||||||
|
GList *graphics;
|
||||||
|
struct gds_graphics *gfx;
|
||||||
|
int layer;
|
||||||
|
GtkWidget *le;
|
||||||
|
|
||||||
|
for (graphics = cell->graphic_objs; graphics != NULL; graphics = graphics->next) {
|
||||||
|
gfx = (struct gds_graphics *)graphics->data;
|
||||||
|
layer = (int)gfx->layer;
|
||||||
|
if (layer_selector_check_if_layer_widget_exists(self, layer) == FALSE) {
|
||||||
|
le = layer_element_new();
|
||||||
|
sel_layer_element_setup_dnd_callbacks(self, LAYER_ELEMENT(le));
|
||||||
|
layer_element_set_layer(LAYER_ELEMENT(le), layer);
|
||||||
|
gtk_list_box_insert(self->list_box, le, -1);
|
||||||
|
gtk_widget_show(le);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sort_func Sort callback for list box
|
||||||
|
* @param row1
|
||||||
|
* @param row2
|
||||||
|
* @param unused
|
||||||
|
* @note Do not use this function. This is an internal callback
|
||||||
|
* @return See sort function documentation of GTK+
|
||||||
|
*/
|
||||||
|
static gint layer_selector_sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
||||||
|
{
|
||||||
|
LayerElement *le1, *le2;
|
||||||
|
gint ret;
|
||||||
|
static const enum layer_selector_sort_algo default_sort = LAYER_SELECTOR_SORT_DOWN;
|
||||||
|
const enum layer_selector_sort_algo *algo = (const enum layer_selector_sort_algo *)unused;
|
||||||
|
|
||||||
|
/* Assume downward sorting */
|
||||||
|
/* TODO: This is nasty. Find a better way */
|
||||||
|
if (!algo)
|
||||||
|
algo = &default_sort;
|
||||||
|
|
||||||
|
le1 = LAYER_ELEMENT(row1);
|
||||||
|
le2 = LAYER_ELEMENT(row2);
|
||||||
|
|
||||||
|
/* Determine sort fow downward sort */
|
||||||
|
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
|
||||||
|
|
||||||
|
/* Change order if upward sort is requested */
|
||||||
|
ret *= (*algo == LAYER_SELECTOR_SORT_DOWN ? 1 : -1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_selector_generate_layer_widgets(LayerSelector *selector, GList *libs)
|
||||||
|
{
|
||||||
|
GList *cell_list = NULL;
|
||||||
|
struct gds_library *lib;
|
||||||
|
|
||||||
|
layer_selector_clear_widgets(selector);
|
||||||
|
|
||||||
|
for (; libs != NULL; libs = libs->next) {
|
||||||
|
lib = (struct gds_library *)libs->data;
|
||||||
|
for (cell_list = lib->cells; cell_list != NULL; cell_list = cell_list->next) {
|
||||||
|
layer_selector_analyze_cell_layers(selector, (struct gds_cell *)cell_list->data);
|
||||||
|
} /* For Cell List */
|
||||||
|
} /* For libs */
|
||||||
|
|
||||||
|
/* Sort the layers */
|
||||||
|
layer_selector_force_sort(selector, LAYER_SELECTOR_SORT_DOWN);
|
||||||
|
|
||||||
|
/* Activate Buttons */
|
||||||
|
if (selector->associated_load_button)
|
||||||
|
gtk_widget_set_sensitive(selector->associated_load_button, TRUE);
|
||||||
|
if (selector->associated_save_button)
|
||||||
|
gtk_widget_set_sensitive(selector->associated_save_button, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find LayerElement in list with specified layer number
|
||||||
|
* @param el_list List with elements of type LayerElement
|
||||||
|
* @param layer Layer number
|
||||||
|
* @return Found LayerElement. If nothing is found, NULL.
|
||||||
|
*/
|
||||||
|
static LayerElement *layer_selector_find_layer_element_in_list(GList *el_list, int layer)
|
||||||
|
{
|
||||||
|
LayerElement *ret = NULL;
|
||||||
|
for (; el_list != NULL; el_list = el_list->next) {
|
||||||
|
if (layer_element_get_layer(LAYER_ELEMENT(el_list->data)) == layer) {
|
||||||
|
ret = LAYER_ELEMENT(el_list->data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load the layer mapping from a CSV formatted file
|
||||||
|
*
|
||||||
|
* This function imports the layer specification from a file (see @ref lmf-spec).
|
||||||
|
* The layer ordering defined in the file is kept. All layers present in the
|
||||||
|
* current loaded library, which are not present in the layer mapping file
|
||||||
|
* are appended at the end of the layer selector list.
|
||||||
|
*
|
||||||
|
* @param self LayerSelector instance
|
||||||
|
* @param file_name File name to load from
|
||||||
|
*/
|
||||||
|
static void layer_selector_load_layer_mapping_from_file(LayerSelector *self, gchar *file_name)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
GFileInputStream *stream;
|
||||||
|
GDataInputStream *dstream;
|
||||||
|
LayerElement *le;
|
||||||
|
char *name;
|
||||||
|
gboolean export;
|
||||||
|
int layer;
|
||||||
|
GdkRGBA color;
|
||||||
|
int result;
|
||||||
|
GList *rows;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
|
file = g_file_new_for_path(file_name);
|
||||||
|
stream = g_file_read(file, NULL, NULL);
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
goto destroy_file;
|
||||||
|
|
||||||
|
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
||||||
|
|
||||||
|
rows = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||||
|
|
||||||
|
/* Reference and remove all rows from box */
|
||||||
|
for (temp = rows; temp != NULL; temp = temp->next) {
|
||||||
|
le = LAYER_ELEMENT(temp->data);
|
||||||
|
/* Referencing protets the widget from being deleted when removed */
|
||||||
|
g_object_ref(G_OBJECT(le));
|
||||||
|
gtk_container_remove(GTK_CONTAINER(self->list_box), GTK_WIDGET(le));
|
||||||
|
}
|
||||||
|
|
||||||
|
while((result = mapping_parser_load_line(dstream, &export, &name, &layer, &color)) >= 0) {
|
||||||
|
/* skip broken line */
|
||||||
|
if (result == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add rows in the same order as in file */
|
||||||
|
if ((le = layer_selector_find_layer_element_in_list(rows, layer))) {
|
||||||
|
gtk_list_box_insert(self->list_box, GTK_WIDGET(le), -1);
|
||||||
|
|
||||||
|
layer_element_set_color(le, &color);
|
||||||
|
layer_element_set_export(le, export);
|
||||||
|
layer_element_set_name(le, name);
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
/* Dereference and remove from list */
|
||||||
|
g_object_unref(G_OBJECT(le));
|
||||||
|
rows = g_list_remove(rows, le);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add remaining elements */
|
||||||
|
for (temp = rows; temp != NULL; temp = temp->next) {
|
||||||
|
le = LAYER_ELEMENT(temp->data);
|
||||||
|
/* Referencing protets the widget from being deleted when removed */
|
||||||
|
gtk_list_box_insert(self->list_box, GTK_WIDGET(le), -1);
|
||||||
|
g_object_unref(G_OBJECT(le));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete list */
|
||||||
|
g_list_free(rows);
|
||||||
|
|
||||||
|
/* read line */
|
||||||
|
g_object_unref(dstream);
|
||||||
|
g_object_unref(stream);
|
||||||
|
destroy_file:
|
||||||
|
g_object_unref(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for Load Mapping Button
|
||||||
|
* @param button
|
||||||
|
* @param user_data
|
||||||
|
*/
|
||||||
|
static void layer_selector_load_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||||
|
{
|
||||||
|
LayerSelector *sel;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
gint res;
|
||||||
|
gchar *file_name;
|
||||||
|
|
||||||
|
sel = LAYER_SELECTOR(user_data);
|
||||||
|
|
||||||
|
dialog = gtk_file_chooser_dialog_new("Load Mapping File", GTK_WINDOW(sel->load_parent_window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
"Cancel", GTK_RESPONSE_CANCEL, "Load Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
|
if (res == GTK_RESPONSE_ACCEPT) {
|
||||||
|
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
|
layer_selector_load_layer_mapping_from_file(sel, file_name);
|
||||||
|
g_free(file_name);
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Save layer mapping of selector \p self to a file
|
||||||
|
* @param self LayerSelector instance
|
||||||
|
* @param file_name File name to save to
|
||||||
|
*/
|
||||||
|
static void layer_selector_save_layer_mapping_data(LayerSelector *self, const gchar *file_name)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char workbuff[512];
|
||||||
|
GList *le_list;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
|
/* Overwrite existing file */
|
||||||
|
file = fopen((const char *)file_name, "w");
|
||||||
|
|
||||||
|
le_list = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||||
|
|
||||||
|
/* File format is CSV: <Layer>,<target_pos>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
|
||||||
|
for (temp = le_list; temp != NULL; temp = temp->next) {
|
||||||
|
/* To be sure it is a valid string */
|
||||||
|
workbuff[0] = 0;
|
||||||
|
mapping_parser_gen_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
|
||||||
|
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(le_list);
|
||||||
|
|
||||||
|
/* Save File */
|
||||||
|
fflush(file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for Save Layer Mapping Button
|
||||||
|
* @param button
|
||||||
|
* @param user_data
|
||||||
|
*/
|
||||||
|
static void layer_selector_save_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkWidget *dialog;
|
||||||
|
gint res;
|
||||||
|
gchar *file_name;
|
||||||
|
LayerSelector *sel;
|
||||||
|
|
||||||
|
sel = LAYER_SELECTOR(user_data);
|
||||||
|
|
||||||
|
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(sel->save_parent_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
|
"Cancel", GTK_RESPONSE_CANCEL, "Save Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||||
|
|
||||||
|
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
|
if (res == GTK_RESPONSE_ACCEPT) {
|
||||||
|
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
|
layer_selector_save_layer_mapping_data(sel, file_name);
|
||||||
|
g_free(file_name);
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_selector_set_load_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window)
|
||||||
|
{
|
||||||
|
g_clear_object(&selector->load_parent_window);
|
||||||
|
g_clear_object(&selector->associated_load_button);
|
||||||
|
|
||||||
|
g_object_ref(G_OBJECT(button));
|
||||||
|
g_object_ref(G_OBJECT(main_window));
|
||||||
|
selector->associated_load_button = button;
|
||||||
|
selector->load_parent_window = main_window;
|
||||||
|
g_signal_connect(button, "clicked", G_CALLBACK(layer_selector_load_mapping_clicked), selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_selector_set_save_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window)
|
||||||
|
{
|
||||||
|
g_clear_object(&selector->save_parent_window);
|
||||||
|
g_clear_object(&selector->associated_save_button);
|
||||||
|
|
||||||
|
g_object_ref(G_OBJECT(button));
|
||||||
|
g_object_ref(G_OBJECT(main_window));
|
||||||
|
selector->associated_save_button = button;
|
||||||
|
selector->save_parent_window = main_window;
|
||||||
|
g_signal_connect(button, "clicked", G_CALLBACK(layer_selector_save_mapping_clicked), selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function)
|
||||||
|
{
|
||||||
|
GtkListBox *box;
|
||||||
|
|
||||||
|
if (!selector)
|
||||||
|
return;
|
||||||
|
|
||||||
|
box = selector->list_box;
|
||||||
|
if (!box)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Set sorting function, sort, and disable sorting function */
|
||||||
|
gtk_list_box_set_sort_func(box, layer_selector_sort_func, (gpointer)&sort_function, NULL);
|
||||||
|
gtk_list_box_invalidate_sort(box);
|
||||||
|
gtk_list_box_set_sort_func(box, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
@@ -25,13 +25,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup Mapping-Parser
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mapping-parser.h"
|
#include <gds-render/layer/mapping-parser.h>
|
||||||
|
|
||||||
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
|
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
gsize len;
|
gsize len;
|
||||||
@@ -94,5 +94,51 @@ ret_direct:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GString *string;
|
||||||
|
gboolean export;
|
||||||
|
const gchar *name;
|
||||||
|
int layer;
|
||||||
|
GdkRGBA color;
|
||||||
|
|
||||||
|
string = g_string_new_len(NULL, max_len-1);
|
||||||
|
|
||||||
|
/* Extract values */
|
||||||
|
export = layer_element_get_export(layer_element);
|
||||||
|
name = (const gchar*)layer_element_get_name(layer_element);
|
||||||
|
layer = layer_element_get_layer(layer_element);
|
||||||
|
layer_element_get_color(layer_element, &color);
|
||||||
|
|
||||||
|
/* print values to line */
|
||||||
|
g_string_printf(string, "%d:%lf:%lf:%lf:%lf:%d:%s\n",
|
||||||
|
layer, color.red, color.green,
|
||||||
|
color.blue, color.alpha, (export == TRUE ? 1 : 0), name);
|
||||||
|
/* Fix broken locale settings */
|
||||||
|
for (i = 0; string->str[i]; i++) {
|
||||||
|
if (string->str[i] == ',')
|
||||||
|
string->str[i] = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; string->str[i]; i++) {
|
||||||
|
if (string->str[i] == ':')
|
||||||
|
string->str[i] = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string->len > (max_len-1)) {
|
||||||
|
printf("Layer Definition too long. Please shorten Layer Name!!\n");
|
||||||
|
line_buffer[0] = 0x0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy max_len bytes of string */
|
||||||
|
strncpy(line_buffer, (char *)string->str, max_len-1);
|
||||||
|
line_buffer[max_len-1] = 0;
|
||||||
|
|
||||||
|
/* Completely remove string */
|
||||||
|
g_string_free(string, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
476
main-window.c
476
main-window.c
@@ -1,476 +0,0 @@
|
|||||||
/*
|
|
||||||
* GDSII-Converter
|
|
||||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*
|
|
||||||
* This file is part of GDSII-Converter.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file main-window.c
|
|
||||||
* @brief Handling of GUI
|
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @addtogroup MainApplication
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main-window.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "gds-parser/gds-parser.h"
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include "layer-selector/layer-selector.h"
|
|
||||||
#include "layer-selector/layer-selector-dnd.h"
|
|
||||||
#include "tree-renderer/tree-store.h"
|
|
||||||
#include "latex-output/latex-output.h"
|
|
||||||
#include "widgets/conv-settings-dialog.h"
|
|
||||||
#include "cairo-output/cairo-output.h"
|
|
||||||
#include "trigonometric/cell-trigonometrics.h"
|
|
||||||
#include "version/version.h"
|
|
||||||
#include "tree-renderer/lib-cell-renderer.h"
|
|
||||||
#include "gds-parser/gds-tree-checker.h"
|
|
||||||
/**
|
|
||||||
* @brief User data supplied to callback function of the open button
|
|
||||||
*/
|
|
||||||
struct open_button_data {
|
|
||||||
GtkWindow *main_window;
|
|
||||||
GList **list_ptr;
|
|
||||||
GtkTreeStore *cell_store;
|
|
||||||
GtkListBox *layer_box;
|
|
||||||
GtkSearchEntry *search_entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief User data supplied to callback function of the convert button
|
|
||||||
*/
|
|
||||||
struct convert_button_data {
|
|
||||||
GtkTreeView *tree_view;
|
|
||||||
GtkWindow *main_window;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Window close event of main window
|
|
||||||
*
|
|
||||||
* Closes the main window. This leads to the termination of the whole application
|
|
||||||
* @param window main window
|
|
||||||
* @param user not used
|
|
||||||
* @return TRUE. This indicates that the event has been fully handled
|
|
||||||
*/
|
|
||||||
static gboolean on_window_close(gpointer window, gpointer user)
|
|
||||||
{
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(window));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief generate string from gds_time_field
|
|
||||||
* @param date Date to convert
|
|
||||||
* @return String with date
|
|
||||||
*/
|
|
||||||
static GString *generate_string_from_date(struct gds_time_field *date)
|
|
||||||
{
|
|
||||||
GString *str;
|
|
||||||
|
|
||||||
str = g_string_new_len(NULL, 50);
|
|
||||||
g_string_printf(str, "%02u.%02u.%u - %02u:%02u",
|
|
||||||
(unsigned int)date->day,
|
|
||||||
(unsigned int)date->month,
|
|
||||||
(unsigned int)date->year,
|
|
||||||
(unsigned int)date->hour,
|
|
||||||
(unsigned int)date->minute);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback function of Load GDS button
|
|
||||||
* @param button
|
|
||||||
* @param user Necessary Data
|
|
||||||
*/
|
|
||||||
static void on_load_gds(gpointer button, gpointer user)
|
|
||||||
{
|
|
||||||
GList *cell;
|
|
||||||
GtkTreeIter libiter;
|
|
||||||
GtkTreeIter celliter;
|
|
||||||
GList *lib;
|
|
||||||
struct gds_library *gds_lib;
|
|
||||||
struct gds_cell *gds_c;
|
|
||||||
struct open_button_data *ptr = (struct open_button_data *)user;
|
|
||||||
GtkTreeStore *store = ptr->cell_store;
|
|
||||||
GtkWidget *open_dialog;
|
|
||||||
GtkFileChooser *file_chooser;
|
|
||||||
GtkFileFilter *filter;
|
|
||||||
GtkStyleContext *button_style;
|
|
||||||
gint dialog_result;
|
|
||||||
int gds_result;
|
|
||||||
char *filename;
|
|
||||||
GString *mod_date;
|
|
||||||
GString *acc_date;
|
|
||||||
unsigned int cell_error_level;
|
|
||||||
|
|
||||||
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", ptr->main_window,
|
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
||||||
"Cancel", GTK_RESPONSE_CANCEL,
|
|
||||||
"Open GDSII", GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
file_chooser = GTK_FILE_CHOOSER(open_dialog);
|
|
||||||
/* Add GDS II Filter */
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_add_pattern(filter, "*.gds");
|
|
||||||
gtk_file_filter_set_name(filter, "GDSII-Files");
|
|
||||||
gtk_file_chooser_add_filter(file_chooser, filter);
|
|
||||||
|
|
||||||
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
|
|
||||||
|
|
||||||
if (dialog_result == GTK_RESPONSE_ACCEPT) {
|
|
||||||
|
|
||||||
/* Get File name */
|
|
||||||
filename = gtk_file_chooser_get_filename(file_chooser);
|
|
||||||
|
|
||||||
gtk_tree_store_clear(store);
|
|
||||||
clear_lib_list(ptr->list_ptr);
|
|
||||||
|
|
||||||
/* Parse new GDSII file */
|
|
||||||
gds_result = parse_gds_from_file(filename, ptr->list_ptr);
|
|
||||||
|
|
||||||
/* Delete file name afterwards */
|
|
||||||
g_free(filename);
|
|
||||||
if (gds_result)
|
|
||||||
goto end_destroy;
|
|
||||||
|
|
||||||
/* remove suggested action from Open button */
|
|
||||||
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
|
|
||||||
gtk_style_context_remove_class(button_style, "suggested-action");
|
|
||||||
|
|
||||||
for (lib = *(ptr->list_ptr); lib != NULL; lib = lib->next) {
|
|
||||||
gds_lib = (struct gds_library *)lib->data;
|
|
||||||
/* Create top level iter */
|
|
||||||
gtk_tree_store_append(store, &libiter, NULL);
|
|
||||||
|
|
||||||
/* Convert dates to String */
|
|
||||||
mod_date = generate_string_from_date(&gds_lib->mod_time);
|
|
||||||
acc_date = generate_string_from_date(&gds_lib->access_time);
|
|
||||||
|
|
||||||
gtk_tree_store_set(store, &libiter,
|
|
||||||
CELL_SEL_LIBRARY, gds_lib,
|
|
||||||
CELL_SEL_MODDATE, mod_date->str,
|
|
||||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
/* Check this library. This might take a while */
|
|
||||||
(void)gds_tree_check_cell_references(gds_lib);
|
|
||||||
(void)gds_tree_check_reference_loops(gds_lib);
|
|
||||||
|
|
||||||
/* Delete GStrings including string data. */
|
|
||||||
/* Cell store copies String type data items */
|
|
||||||
g_string_free(mod_date, TRUE);
|
|
||||||
g_string_free(acc_date, TRUE);
|
|
||||||
|
|
||||||
for (cell = gds_lib->cells; cell != NULL; cell = cell->next) {
|
|
||||||
gds_c = (struct gds_cell *)cell->data;
|
|
||||||
gtk_tree_store_append(store, &celliter, &libiter);
|
|
||||||
|
|
||||||
/* Convert dates to String */
|
|
||||||
mod_date = generate_string_from_date(&gds_c->mod_time);
|
|
||||||
acc_date = generate_string_from_date(&gds_c->access_time);
|
|
||||||
|
|
||||||
/* Get the checking results for this cell */
|
|
||||||
cell_error_level = 0;
|
|
||||||
if (gds_c->checks.unresolved_child_count)
|
|
||||||
cell_error_level |= LIB_CELL_RENDERER_ERROR_WARN;
|
|
||||||
|
|
||||||
/* Check if it is completely b0rken */
|
|
||||||
if (gds_c->checks.affected_by_reference_loop)
|
|
||||||
cell_error_level |= LIB_CELL_RENDERER_ERROR_ERR;
|
|
||||||
|
|
||||||
/* Add cell to tree store model */
|
|
||||||
gtk_tree_store_set(store, &celliter,
|
|
||||||
CELL_SEL_CELL, gds_c,
|
|
||||||
CELL_SEL_MODDATE, mod_date->str,
|
|
||||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
|
||||||
CELL_SEL_CELL_ERROR_STATE, cell_error_level,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
/* Delete GStrings including string data. */
|
|
||||||
/* Cell store copies String type data items */
|
|
||||||
g_string_free(mod_date, TRUE);
|
|
||||||
g_string_free(acc_date, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create Layers in Layer Box */
|
|
||||||
generate_layer_widgets(ptr->layer_box, *(ptr->list_ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
end_destroy:
|
|
||||||
/* Destroy dialog and filter */
|
|
||||||
gtk_widget_destroy(open_dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert button callback
|
|
||||||
* @param button
|
|
||||||
* @param user
|
|
||||||
*/
|
|
||||||
static void on_convert_clicked(gpointer button, gpointer user)
|
|
||||||
{
|
|
||||||
(void)button;
|
|
||||||
static struct render_settings sett = {
|
|
||||||
.scale = 1000.0,
|
|
||||||
.renderer = RENDERER_LATEX_TIKZ,
|
|
||||||
};
|
|
||||||
struct convert_button_data *data = (struct convert_button_data *)user;
|
|
||||||
GtkTreeSelection *selection;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
GtkTreeModel *model;
|
|
||||||
GList *layer_list;
|
|
||||||
struct gds_cell *cell_to_render;
|
|
||||||
FILE *output_file;
|
|
||||||
GtkWidget *dialog;
|
|
||||||
RendererSettingsDialog *settings;
|
|
||||||
GtkFileFilter *filter;
|
|
||||||
gint res;
|
|
||||||
char *file_name;
|
|
||||||
union bounding_box cell_box;
|
|
||||||
unsigned int height, width;
|
|
||||||
|
|
||||||
if (!data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Get selected cell */
|
|
||||||
selection = gtk_tree_view_get_selection(data->tree_view);
|
|
||||||
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell_to_render, -1);
|
|
||||||
|
|
||||||
if (!cell_to_render)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Get layers that are rendered */
|
|
||||||
layer_list = export_rendered_layer_info();
|
|
||||||
|
|
||||||
/* Calculate cell size in DB units */
|
|
||||||
bounding_box_prepare_empty(&cell_box);
|
|
||||||
calculate_cell_bounding_box(&cell_box, cell_to_render);
|
|
||||||
|
|
||||||
/* Calculate size in database units
|
|
||||||
* Note that the results are bound to be positive,
|
|
||||||
* so casting them to unsigned int is asbsolutely valid
|
|
||||||
*/
|
|
||||||
height = (unsigned int)(cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y);
|
|
||||||
width = (unsigned int)(cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x);
|
|
||||||
|
|
||||||
/* Show settings dialog */
|
|
||||||
settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window));
|
|
||||||
renderer_settings_dialog_set_settings(settings, &sett);
|
|
||||||
renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters);
|
|
||||||
renderer_settings_dialog_set_cell_height(settings, height);
|
|
||||||
renderer_settings_dialog_set_cell_width(settings, width);
|
|
||||||
|
|
||||||
res = gtk_dialog_run(GTK_DIALOG(settings));
|
|
||||||
if (res == GTK_RESPONSE_OK) {
|
|
||||||
renderer_settings_dialog_get_settings(settings, &sett);
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(settings));
|
|
||||||
} else {
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(settings));
|
|
||||||
goto ret_layer_destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save file dialog */
|
|
||||||
dialog = gtk_file_chooser_dialog_new((sett.renderer == RENDERER_LATEX_TIKZ
|
|
||||||
? "Save LaTeX File" : "Save PDF"),
|
|
||||||
GTK_WINDOW(data->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
|
|
||||||
/* Set file filter according to settings */
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
switch (sett.renderer) {
|
|
||||||
case RENDERER_LATEX_TIKZ:
|
|
||||||
gtk_file_filter_add_pattern(filter, "*.tex");
|
|
||||||
gtk_file_filter_set_name(filter, "LaTeX-Files");
|
|
||||||
break;
|
|
||||||
case RENDERER_CAIROGRAPHICS_PDF:
|
|
||||||
gtk_file_filter_add_pattern(filter, "*.pdf");
|
|
||||||
gtk_file_filter_set_name(filter, "PDF-Files");
|
|
||||||
break;
|
|
||||||
case RENDERER_CAIROGRAPHICS_SVG:
|
|
||||||
gtk_file_filter_add_pattern(filter, "*.svg");
|
|
||||||
gtk_file_filter_set_name(filter, "SVG-Files");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
|
||||||
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
|
|
||||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
|
||||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
|
|
||||||
switch (sett.renderer) {
|
|
||||||
case RENDERER_LATEX_TIKZ:
|
|
||||||
output_file = fopen(file_name, "w");
|
|
||||||
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett.scale,
|
|
||||||
sett.tex_pdf_layers, sett.tex_standalone);
|
|
||||||
fclose(output_file);
|
|
||||||
break;
|
|
||||||
case RENDERER_CAIROGRAPHICS_SVG:
|
|
||||||
case RENDERER_CAIROGRAPHICS_PDF:
|
|
||||||
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
|
||||||
(sett.renderer == RENDERER_CAIROGRAPHICS_PDF
|
|
||||||
? file_name
|
|
||||||
: NULL),
|
|
||||||
(sett.renderer == RENDERER_CAIROGRAPHICS_SVG
|
|
||||||
? file_name
|
|
||||||
: NULL),
|
|
||||||
sett.scale);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_free(file_name);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
ret_layer_destroy:
|
|
||||||
g_list_free_full(layer_list, (GDestroyNotify)delete_layer_info_struct);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief cell_tree_view_activated
|
|
||||||
* @param tree_view Not used
|
|
||||||
* @param user convert button data
|
|
||||||
*/
|
|
||||||
static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
|
|
||||||
GtkTreeViewColumn *column, gpointer user)
|
|
||||||
{
|
|
||||||
(void)tree_view;
|
|
||||||
(void)path;
|
|
||||||
(void)column;
|
|
||||||
|
|
||||||
on_convert_clicked(NULL, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback for cell-selection change event
|
|
||||||
*
|
|
||||||
* This function activates/deactivates the convert button depending on whether
|
|
||||||
* a cell is selected for conversion or not
|
|
||||||
* @param sel
|
|
||||||
* @param convert_button
|
|
||||||
*/
|
|
||||||
static void cell_selection_changed(GtkTreeSelection *sel, GtkWidget *convert_button)
|
|
||||||
{
|
|
||||||
GtkTreeModel *model = NULL;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
|
|
||||||
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
|
|
||||||
/* Node selected. Show button */
|
|
||||||
gtk_widget_set_sensitive(convert_button, TRUE);
|
|
||||||
} else {
|
|
||||||
gtk_widget_set_sensitive(convert_button, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sort_up_callback(GtkWidget *widget, gpointer user)
|
|
||||||
{
|
|
||||||
(void)widget;
|
|
||||||
(void)user;
|
|
||||||
|
|
||||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sort_down_callback(GtkWidget *widget, gpointer user)
|
|
||||||
{
|
|
||||||
(void)widget;
|
|
||||||
(void)user;
|
|
||||||
|
|
||||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWindow *create_main_window()
|
|
||||||
{
|
|
||||||
GtkBuilder *main_builder;
|
|
||||||
GtkTreeView *cell_tree;
|
|
||||||
GtkWidget *listbox;
|
|
||||||
GtkWidget *conv_button;
|
|
||||||
GtkWidget *search_entry;
|
|
||||||
GtkHeaderBar *header_bar;
|
|
||||||
static GList *gds_libs;
|
|
||||||
static struct open_button_data open_data;
|
|
||||||
static struct convert_button_data conv_data;
|
|
||||||
struct tree_stores *cell_selector_stores;
|
|
||||||
GtkWidget *sort_up_button;
|
|
||||||
GtkWidget *sort_down_button;
|
|
||||||
|
|
||||||
main_builder = gtk_builder_new_from_resource("/main.glade");
|
|
||||||
gtk_builder_connect_signals(main_builder, NULL);
|
|
||||||
|
|
||||||
cell_tree = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree"));
|
|
||||||
search_entry = GTK_WIDGET(gtk_builder_get_object(main_builder, "cell-search"));
|
|
||||||
open_data.search_entry = GTK_SEARCH_ENTRY(search_entry);
|
|
||||||
cell_selector_stores = setup_cell_selector(cell_tree, GTK_ENTRY(search_entry));
|
|
||||||
|
|
||||||
open_data.cell_store = cell_selector_stores->base_store;
|
|
||||||
open_data.list_ptr = &gds_libs;
|
|
||||||
open_data.main_window = GTK_WINDOW(gtk_builder_get_object(main_builder, "main-window"));
|
|
||||||
g_signal_connect(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds")),
|
|
||||||
"clicked", G_CALLBACK(on_load_gds), (gpointer)&open_data);
|
|
||||||
|
|
||||||
/* Connect delete-event */
|
|
||||||
g_signal_connect(GTK_WIDGET(open_data.main_window), "delete-event",
|
|
||||||
G_CALLBACK(on_window_close), NULL);
|
|
||||||
|
|
||||||
/* Connect Convert button */
|
|
||||||
conv_data.tree_view = cell_tree;
|
|
||||||
conv_data.main_window = open_data.main_window;
|
|
||||||
|
|
||||||
conv_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
|
|
||||||
g_signal_connect(conv_button, "clicked", G_CALLBACK(on_convert_clicked), &conv_data);
|
|
||||||
|
|
||||||
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
|
|
||||||
/* Set up the list box sided callbacks for drag and drop */
|
|
||||||
layer_selector_list_box_setup_dnd(GTK_LIST_BOX(listbox));
|
|
||||||
|
|
||||||
open_data.layer_box = GTK_LIST_BOX(listbox);
|
|
||||||
|
|
||||||
/* Set buttons fpr layer mapping GUI */
|
|
||||||
setup_load_mapping_callback(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping")),
|
|
||||||
open_data.main_window);
|
|
||||||
setup_save_mapping_callback(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping")),
|
|
||||||
open_data.main_window);
|
|
||||||
|
|
||||||
/* Callback for selection change of cell selector */
|
|
||||||
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(cell_tree)), "changed",
|
|
||||||
G_CALLBACK(cell_selection_changed), conv_button);
|
|
||||||
g_signal_connect(cell_tree, "row-activated", G_CALLBACK(cell_tree_view_activated), &conv_data);
|
|
||||||
|
|
||||||
/* Set version in main window subtitle */
|
|
||||||
header_bar = GTK_HEADER_BAR(gtk_builder_get_object(main_builder, "header-bar"));
|
|
||||||
gtk_header_bar_set_subtitle(header_bar, _app_version_string);
|
|
||||||
|
|
||||||
/* Get layer sorting buttons and set callbacks */
|
|
||||||
sort_up_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-up-sort"));
|
|
||||||
sort_down_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-down-sort"));
|
|
||||||
|
|
||||||
g_signal_connect(sort_up_button, "clicked", G_CALLBACK(sort_up_callback), NULL);
|
|
||||||
g_signal_connect(sort_down_button, "clicked", G_CALLBACK(sort_down_callback), NULL);
|
|
||||||
|
|
||||||
g_object_unref(main_builder);
|
|
||||||
|
|
||||||
return conv_data.main_window;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
154
main.c
154
main.c
@@ -17,76 +17,185 @@
|
|||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file main.c
|
||||||
|
* @brief main.c
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "main-window.h"
|
|
||||||
#include "command-line.h"
|
|
||||||
#include "external-renderer.h"
|
|
||||||
#include "version/version.h"
|
|
||||||
|
|
||||||
|
#include <gds-render/gds-render-gui.h>
|
||||||
|
#include <gds-render/command-line.h>
|
||||||
|
#include <gds-render/external-renderer.h>
|
||||||
|
#include <gds-render/version.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure containing The GtkApplication and a list containing the GdsRenderGui objects.
|
||||||
|
*/
|
||||||
struct application_data {
|
struct application_data {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
GtkWindow *main_window;
|
GList *gui_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for the menu entry 'Quit'
|
||||||
|
*
|
||||||
|
* Destroys all GUIs contained in the application_data structure
|
||||||
|
* provided by \p user_data.
|
||||||
|
*
|
||||||
|
* The complete suspension of all main windows leads to the termination of the
|
||||||
|
* GApplication.
|
||||||
|
*
|
||||||
|
* @param action unused
|
||||||
|
* @param parameter unused
|
||||||
|
* @param user_data application_data structure
|
||||||
|
*/
|
||||||
static void app_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
static void app_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||||
{
|
{
|
||||||
const struct application_data * const appdata = (const struct application_data *)user_data;
|
struct application_data * const appdata = (struct application_data *)user_data;
|
||||||
(void)action;
|
(void)action;
|
||||||
(void)parameter;
|
(void)parameter;
|
||||||
|
GList *list_iter;
|
||||||
|
GdsRenderGui *gui;
|
||||||
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(appdata->main_window));
|
/* Dispose all GUIs */
|
||||||
|
for (list_iter = appdata->gui_list; list_iter != NULL; list_iter = g_list_next(list_iter)) {
|
||||||
|
gui = RENDERER_GUI(list_iter->data);
|
||||||
|
g_object_unref(gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(appdata->gui_list);
|
||||||
|
appdata->gui_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for the 'About' menu entry
|
||||||
|
*
|
||||||
|
* This function shows the about dialog.
|
||||||
|
*
|
||||||
|
* @param action GSimpleAction, unused
|
||||||
|
* @param parameter Unused.
|
||||||
|
* @param user_data Unused
|
||||||
|
*/
|
||||||
static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||||
{
|
{
|
||||||
GtkBuilder *builder;
|
GtkBuilder *builder;
|
||||||
GtkDialog *dialog;
|
GtkDialog *dialog;
|
||||||
const struct application_data * const appdata = (const struct application_data *)user_data;
|
GdkPixbuf *logo_buf;
|
||||||
|
GError *error = NULL;
|
||||||
|
(void)user_data;
|
||||||
(void)action;
|
(void)action;
|
||||||
(void)parameter;
|
(void)parameter;
|
||||||
|
|
||||||
builder = gtk_builder_new_from_resource("/about.glade");
|
builder = gtk_builder_new_from_resource("/about.glade");
|
||||||
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
|
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
|
||||||
gtk_window_set_transient_for(GTK_WINDOW(dialog), appdata->main_window);
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), NULL);
|
||||||
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), _app_version_string);
|
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), _app_version_string);
|
||||||
|
|
||||||
|
/* Load icon from resource */
|
||||||
|
logo_buf = gdk_pixbuf_new_from_resource_at_scale("/logo.svg", 100, 100, TRUE, &error);
|
||||||
|
if (logo_buf) {
|
||||||
|
/* Set logo */
|
||||||
|
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), logo_buf);
|
||||||
|
|
||||||
|
/* Pixbuf is now owned by about dialog. Unref */
|
||||||
|
g_object_unref(logo_buf);
|
||||||
|
} else if (error) {
|
||||||
|
fprintf(stderr, "Logo could not be displayed: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_dialog_run(dialog);
|
gtk_dialog_run(dialog);
|
||||||
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(dialog));
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
||||||
g_object_unref(builder);
|
g_object_unref(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains the application menu entries
|
||||||
|
*/
|
||||||
const static GActionEntry app_actions[] = {
|
const static GActionEntry app_actions[] = {
|
||||||
{"quit", app_quit, NULL, NULL, NULL, {0}},
|
{"quit", app_quit, NULL, NULL, NULL, {0}},
|
||||||
{"about", app_about, NULL, NULL, NULL, {0}}
|
{"about", app_about, NULL, NULL, NULL, {0}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when a GUI main window is closed
|
||||||
|
*
|
||||||
|
* The GdsRenderGui object associated with the closed main window
|
||||||
|
* is removed from the list of open GUIs (\p user_data) and unreferenced.
|
||||||
|
*
|
||||||
|
* @param gui The GUI instance the closed main window belongs to
|
||||||
|
* @param user_data List of GUIs
|
||||||
|
*/
|
||||||
|
static void gui_window_closed_callback(GdsRenderGui *gui, gpointer user_data)
|
||||||
|
{
|
||||||
|
GList **gui_list = (GList **)user_data;
|
||||||
|
|
||||||
|
/* Dispose of Gui element */
|
||||||
|
*gui_list = g_list_remove(*gui_list, gui);
|
||||||
|
g_object_unref(gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Activation of the GUI
|
||||||
|
* @param app The GApplication reference
|
||||||
|
* @param user_data Used to store the individual GUI instances.
|
||||||
|
*/
|
||||||
static void gapp_activate(GApplication *app, gpointer user_data)
|
static void gapp_activate(GApplication *app, gpointer user_data)
|
||||||
{
|
{
|
||||||
GtkWindow *main_window;
|
GtkWindow *main_window;
|
||||||
|
GdsRenderGui *gui;
|
||||||
|
|
||||||
struct application_data * const appdata = (struct application_data *)user_data;
|
struct application_data * const appdata = (struct application_data *)user_data;
|
||||||
|
|
||||||
main_window = create_main_window();
|
gui = gds_render_gui_new();
|
||||||
appdata->main_window = main_window;
|
appdata->gui_list = g_list_append(appdata->gui_list, gui);
|
||||||
|
|
||||||
|
g_signal_connect(gui, "window-closed", G_CALLBACK(gui_window_closed_callback), &appdata->gui_list);
|
||||||
|
|
||||||
|
main_window = gds_render_gui_get_main_window(gui);
|
||||||
|
|
||||||
gtk_application_add_window(GTK_APPLICATION(app), main_window);
|
gtk_application_add_window(GTK_APPLICATION(app), main_window);
|
||||||
gtk_widget_show(GTK_WIDGET(main_window));
|
gtk_widget_show(GTK_WIDGET(main_window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start the graphical interface.
|
||||||
|
*
|
||||||
|
* This function starts the GUI. If there's already a
|
||||||
|
* running instance of this program, a second window will be
|
||||||
|
* created in that instance and the second one is terminated.
|
||||||
|
*
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
static int start_gui(int argc, char **argv)
|
static int start_gui(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
GtkApplication *gapp;
|
GtkApplication *gapp;
|
||||||
int app_status;
|
int app_status;
|
||||||
static struct application_data appdata;
|
static struct application_data appdata = {
|
||||||
|
.gui_list = NULL
|
||||||
|
};
|
||||||
GMenu *menu;
|
GMenu *menu;
|
||||||
GMenu *m_quit;
|
GMenu *m_quit;
|
||||||
GMenu *m_about;
|
GMenu *m_about;
|
||||||
|
|
||||||
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_NON_UNIQUE);
|
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
|
||||||
g_application_register(G_APPLICATION(gapp), NULL, NULL);
|
g_application_register(G_APPLICATION(gapp), NULL, NULL);
|
||||||
g_signal_connect(gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
|
g_signal_connect(gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
|
||||||
|
|
||||||
|
if (g_application_get_is_remote(G_APPLICATION(gapp)) == TRUE) {
|
||||||
|
g_application_activate(G_APPLICATION(gapp));
|
||||||
|
printf("There is already an open instance. Will open second window in said instance.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
menu = g_menu_new();
|
menu = g_menu_new();
|
||||||
m_quit = g_menu_new();
|
m_quit = g_menu_new();
|
||||||
m_about = g_menu_new();
|
m_about = g_menu_new();
|
||||||
@@ -105,17 +214,29 @@ static int start_gui(int argc, char **argv)
|
|||||||
app_status = g_application_run(G_APPLICATION(gapp), argc, argv);
|
app_status = g_application_run(G_APPLICATION(gapp), argc, argv);
|
||||||
g_object_unref(gapp);
|
g_object_unref(gapp);
|
||||||
|
|
||||||
|
g_list_free(appdata.gui_list);
|
||||||
|
|
||||||
return app_status;
|
return app_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_version()
|
/**
|
||||||
|
* @brief Print the application version string to stdout
|
||||||
|
*/
|
||||||
|
static void print_version(void)
|
||||||
{
|
{
|
||||||
printf("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n",
|
printf("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n",
|
||||||
_app_version_string);
|
_app_version_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The "entry point" of the application
|
||||||
|
* @param argc Number of command line parameters
|
||||||
|
* @param argv Command line parameters
|
||||||
|
* @return Execution status of the application
|
||||||
|
*/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
gchar *gds_name;
|
gchar *gds_name;
|
||||||
@@ -173,6 +294,11 @@ int main(int argc, char **argv)
|
|||||||
/* Get gds name */
|
/* Get gds name */
|
||||||
gds_name = argv[1];
|
gds_name = argv[1];
|
||||||
|
|
||||||
|
/* Print out additional arguments as ignored */
|
||||||
|
for (i = 2; i < argc; i++) {
|
||||||
|
printf("Ignored argument: %s", argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if PDF/TeX names are supplied. if not generate */
|
/* Check if PDF/TeX names are supplied. if not generate */
|
||||||
basename = g_path_get_basename(gds_name);
|
basename = g_path_get_basename(gds_name);
|
||||||
|
|
||||||
|
@@ -17,8 +17,19 @@
|
|||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib-cell-renderer.h"
|
/**
|
||||||
#include "../gds-parser/gds-types.h"
|
* @file lib-cell-renderer.c
|
||||||
|
* @brief LibCellRenderer GObject Class
|
||||||
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup LibCellRenderer
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||||
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
|
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
|
||||||
|
|
||||||
@@ -107,11 +118,12 @@ static void lib_cell_renderer_get_property(GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GParamSpec *properties [PROP_COUNT];
|
static GParamSpec *properties[PROP_COUNT];
|
||||||
|
|
||||||
void lib_cell_renderer_class_init(LibCellRendererClass *klass)
|
void lib_cell_renderer_class_init(LibCellRendererClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
oclass->constructed = lib_cell_renderer_constructed;
|
oclass->constructed = lib_cell_renderer_constructed;
|
||||||
oclass->set_property = lib_cell_renderer_set_property;
|
oclass->set_property = lib_cell_renderer_set_property;
|
||||||
oclass->get_property = lib_cell_renderer_get_property;
|
oclass->get_property = lib_cell_renderer_get_property;
|
||||||
@@ -132,3 +144,5 @@ GtkCellRenderer *lib_cell_renderer_new()
|
|||||||
{
|
{
|
||||||
return GTK_CELL_RENDERER(g_object_new(TYPE_LIB_CELL_RENDERER, NULL));
|
return GTK_CELL_RENDERER(g_object_new(TYPE_LIB_CELL_RENDERER, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
@@ -24,13 +24,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @addtogroup GUI
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tree-store.h"
|
#include <gds-render/tree-renderer/tree-store.h>
|
||||||
#include "lib-cell-renderer.h"
|
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||||
#include "../gds-parser/gds-types.h"
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief this function olny allows cells to be selected
|
* @brief this function olny allows cells to be selected
|
||||||
@@ -51,6 +51,9 @@ static gboolean tree_sel_func(GtkTreeSelection *selection,
|
|||||||
struct gds_cell *cell;
|
struct gds_cell *cell;
|
||||||
unsigned int error_level;
|
unsigned int error_level;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
(void)selection;
|
||||||
|
(void)path_currently_selected;
|
||||||
|
(void)data;
|
||||||
|
|
||||||
gtk_tree_model_get_iter(model, &iter, path);
|
gtk_tree_model_get_iter(model, &iter, path);
|
||||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, CELL_SEL_CELL_ERROR_STATE, &error_level, -1);
|
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, CELL_SEL_CELL_ERROR_STATE, &error_level, -1);
|
||||||
@@ -112,6 +115,8 @@ exit_filter:
|
|||||||
static void change_filter(GtkWidget *entry, gpointer data)
|
static void change_filter(GtkWidget *entry, gpointer data)
|
||||||
{
|
{
|
||||||
struct tree_stores *stores = (struct tree_stores *)data;
|
struct tree_stores *stores = (struct tree_stores *)data;
|
||||||
|
(void)entry;
|
||||||
|
|
||||||
gtk_tree_model_filter_refilter(stores->filter);
|
gtk_tree_model_filter_refilter(stores->filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
git describe --tags
|
git describe --tags --dirty
|
||||||
|
@@ -17,13 +17,15 @@
|
|||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MainApplication
|
* @defgroup version Version Number
|
||||||
|
* See @ref git-version-num
|
||||||
|
* @addtogroup version
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef PROJECT_GIT_VERSION
|
#ifdef PROJECT_GIT_VERSION
|
||||||
|
|
||||||
#define xstr(a) str(a)
|
#define xstr(a) str(a)
|
||||||
#define str(a) #a
|
#define str(a) #a
|
||||||
const char *_app_version_string = xstr(PROJECT_GIT_VERSION);
|
const char *_app_version_string = xstr(PROJECT_GIT_VERSION);
|
||||||
|
@@ -24,11 +24,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Widgets
|
* @addtogroup RendererSettingsDialog
|
||||||
|
* @ingroup Widgets
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "conv-settings-dialog.h"
|
#include <gds-render/widgets/conv-settings-dialog.h>
|
||||||
|
|
||||||
struct _RendererSettingsDialog {
|
struct _RendererSettingsDialog {
|
||||||
GtkDialog parent;
|
GtkDialog parent;
|
||||||
@@ -53,10 +54,60 @@ struct _RendererSettingsDialog {
|
|||||||
|
|
||||||
G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG)
|
G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_CELL_NAME = 1,
|
||||||
|
PROP_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *properties[PROP_COUNT];
|
||||||
|
|
||||||
|
static void renderer_settings_dialog_set_property(GObject *object, guint property_id,
|
||||||
|
const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
const gchar *title = NULL;
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_CELL_NAME:
|
||||||
|
title = g_value_get_string(value);
|
||||||
|
if (title)
|
||||||
|
gtk_window_set_title(GTK_WINDOW(object), title);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void renderer_settings_dialog_get_property(GObject *object, guint property_id,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
const gchar *title;
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_CELL_NAME:
|
||||||
|
title = gtk_window_get_title(GTK_WINDOW(object));
|
||||||
|
g_value_set_string(value, title);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
|
static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
|
||||||
{
|
{
|
||||||
/* No special code needed. Child cells are destroyed automatically due to reference counter */
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
return;
|
|
||||||
|
/* Override virtual functions */
|
||||||
|
oclass->set_property = renderer_settings_dialog_set_property;
|
||||||
|
oclass->get_property = renderer_settings_dialog_get_property;
|
||||||
|
|
||||||
|
properties[PROP_CELL_NAME] = g_param_spec_string("cell-name",
|
||||||
|
"cell-name",
|
||||||
|
"Cell name to be displayed in header bar",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_properties(oclass, PROP_COUNT, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_tex_options(RendererSettingsDialog *self)
|
static void show_tex_options(RendererSettingsDialog *self)
|
||||||
@@ -140,6 +191,11 @@ static double convert_number_to_engineering(double input, const char **out_prefi
|
|||||||
1E2, 1E3, 1E6, 1E9, 1E12, 1E15, 1E18, 1E21, 1E24};
|
1E2, 1E3, 1E6, 1E9, 1E12, 1E15, 1E18, 1E21, 1E24};
|
||||||
const int prefix_count = (int)(sizeof(prefixes)/sizeof(char *));
|
const int prefix_count = (int)(sizeof(prefixes)/sizeof(char *));
|
||||||
|
|
||||||
|
/* If pointer is invalid, return NaN */
|
||||||
|
if (!out_prefix)
|
||||||
|
return 0.0 / 0.0;
|
||||||
|
|
||||||
|
/* Start with the 2nd smallest prefix */
|
||||||
for (idx = 1; idx < prefix_count; idx++) {
|
for (idx = 1; idx < prefix_count; idx++) {
|
||||||
if (input < scale[idx]) {
|
if (input < scale[idx]) {
|
||||||
/* This prefix is bigger than the number. Take the previous one */
|
/* This prefix is bigger than the number. Take the previous one */
|
||||||
@@ -212,7 +268,7 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self)
|
|||||||
GtkWidget *box;
|
GtkWidget *box;
|
||||||
GtkDialog *dialog;
|
GtkDialog *dialog;
|
||||||
|
|
||||||
dialog = &(self->parent);
|
dialog = &self->parent;
|
||||||
|
|
||||||
builder = gtk_builder_new_from_resource("/dialog.glade");
|
builder = gtk_builder_new_from_resource("/dialog.glade");
|
||||||
box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
|
box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
|
||||||
@@ -260,10 +316,7 @@ RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
|
|||||||
|
|
||||||
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
|
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
|
||||||
{
|
{
|
||||||
/*GList *radio_buttons;
|
|
||||||
*GList *temp_button_list;
|
|
||||||
*GtkToggleButton *temp_button = NULL;
|
|
||||||
*/
|
|
||||||
if (!settings || !dialog)
|
if (!settings || !dialog)
|
||||||
return;
|
return;
|
||||||
settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));
|
settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));
|
||||||
|
@@ -31,11 +31,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Widgets
|
* @addtogroup LayerElement
|
||||||
|
* @ingroup Widgets
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "layer-element.h"
|
#include <gds-render/widgets/layer-element.h>
|
||||||
|
|
||||||
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
|
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
|
||||||
|
|
||||||
@@ -57,65 +58,6 @@ static void layer_element_class_init(LayerElementClass *klass)
|
|||||||
oclass->constructed = layer_element_constructed;
|
oclass->constructed = layer_element_constructed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkTargetEntry entries[] = {
|
|
||||||
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void layer_element_drag_begin(GtkWidget *widget,
|
|
||||||
GdkDragContext *context,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *row;
|
|
||||||
GtkAllocation alloc;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
int x, y;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
|
|
||||||
gtk_widget_get_allocation(row, &alloc);
|
|
||||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
|
|
||||||
cr = cairo_create(surface);
|
|
||||||
|
|
||||||
gtk_style_context_add_class (gtk_widget_get_style_context(row), "drag-icon");
|
|
||||||
gtk_widget_draw (row, cr);
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-icon");
|
|
||||||
|
|
||||||
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
|
|
||||||
cairo_surface_set_device_offset (surface, -x, -y);
|
|
||||||
gtk_drag_set_icon_surface (context, surface);
|
|
||||||
|
|
||||||
cairo_destroy (cr);
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
|
|
||||||
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
|
|
||||||
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_element_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *row;
|
|
||||||
(void)context;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
|
|
||||||
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL);
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-row");
|
|
||||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-hover");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data,
|
|
||||||
guint info, guint time, gpointer data)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
(void)info;
|
|
||||||
(void)time;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
gtk_selection_data_set(selection_data, gdk_atom_intern_static_string("GTK_LIST_BOX_ROW"),
|
|
||||||
32, (const guchar *)&widget, sizeof(gpointer));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_element_init(LayerElement *self)
|
static void layer_element_init(LayerElement *self)
|
||||||
{
|
{
|
||||||
GtkBuilder *builder;
|
GtkBuilder *builder;
|
||||||
@@ -131,13 +73,6 @@ static void layer_element_init(LayerElement *self)
|
|||||||
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
|
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
|
||||||
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
|
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
|
||||||
|
|
||||||
/* Setup drag and drop */
|
|
||||||
gtk_style_context_add_class (gtk_widget_get_style_context(GTK_WIDGET(self)), "row");
|
|
||||||
gtk_drag_source_set(GTK_WIDGET(self->priv.event_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
|
|
||||||
g_signal_connect(self->priv.event_handle, "drag-begin", G_CALLBACK(layer_element_drag_begin), NULL);
|
|
||||||
g_signal_connect(self->priv.event_handle, "drag-data-get", G_CALLBACK(layer_element_drag_data_get), NULL);
|
|
||||||
g_signal_connect(self->priv.event_handle, "drag-end", G_CALLBACK(layer_element_drag_end), NULL);
|
|
||||||
|
|
||||||
g_object_unref(builder);
|
g_object_unref(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,12 +121,30 @@ void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
|
|||||||
{
|
{
|
||||||
if (!rgba)
|
if (!rgba)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
|
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
|
||||||
{
|
{
|
||||||
|
if (!elem || !rgba)
|
||||||
|
return;
|
||||||
|
|
||||||
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void layer_element_set_dnd_callbacks(LayerElement *elem, struct layer_element_dnd_data *data)
|
||||||
|
{
|
||||||
|
if (!elem || !data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Setup drag and drop */
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context(GTK_WIDGET(elem)), "row");
|
||||||
|
gtk_drag_source_set(GTK_WIDGET(elem->priv.event_handle), GDK_BUTTON1_MASK, data->entries, data->entry_count, GDK_ACTION_MOVE);
|
||||||
|
g_signal_connect(elem->priv.event_handle, "drag-begin", G_CALLBACK(data->drag_begin), NULL);
|
||||||
|
g_signal_connect(elem->priv.event_handle, "drag-data-get", G_CALLBACK(data->drag_data_get), NULL);
|
||||||
|
g_signal_connect(elem->priv.event_handle, "drag-end", G_CALLBACK(data->drag_end), NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
Reference in New Issue
Block a user