Commit ea38af91 authored by charras's avatar charras

doc update and some minor enhancements before Release Candidate

parent f83bc3e3
......@@ -108,7 +108,7 @@ GLuint Pcb3D_GLCanvas::CreateDrawGL_List()
g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y;
g_Parm_3D_Visu.m_Layers = pcb->m_BoardSettings->m_CopperLayerCount;
g_Parm_3D_Visu.m_BoardScale = 2.0 / MAX( g_Parm_3D_Visu.m_BoardSize.x,
g_Parm_3D_Visu.m_BoardSize.y );
g_Parm_3D_Visu.m_BoardSize.y );
double epoxy_width = 1.6; // epoxy width in mm
g_Parm_3D_Visu.m_Epoxy_Width = epoxy_width / 2.54 * 1000
* g_Parm_3D_Visu.m_BoardScale;
......@@ -190,8 +190,8 @@ GLuint Pcb3D_GLCanvas::CreateDrawGL_List()
/* move the board in order to draw it with its centre at 0,0 3D coordinates */
glTranslatef( -g_Parm_3D_Visu.m_BoardPos.x * g_Parm_3D_Visu.m_BoardScale,
-g_Parm_3D_Visu.m_BoardPos.y * g_Parm_3D_Visu.m_BoardScale,
0.0F );
-g_Parm_3D_Visu.m_BoardPos.y * g_Parm_3D_Visu.m_BoardScale,
0.0F );
glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
/* draw tracks and vias : */
......@@ -205,11 +205,58 @@ GLuint Pcb3D_GLCanvas::CreateDrawGL_List()
if( g_Parm_3D_Visu.m_Draw3DZone )
{
// Draw segments used to fill copper areas
for( segzone = pcb->m_Zone; segzone != NULL; segzone = segzone->Next() )
{
if( segzone->Type() == TYPE_ZONE )
Draw3D_Track( segzone );
}
// Draw copper areas outlines
for( ii = 0; ii < pcb->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* zone = pcb->GetArea( ii );
if( zone->m_FilledPolysList.size() == 0 )
continue;
if( zone->m_ZoneMinThickness <= 1 )
continue;
int imax = zone->m_FilledPolysList.size() - 1;
CPolyPt* firstcorner = &zone->m_FilledPolysList[0];
CPolyPt* begincorner = firstcorner;
SEGZONE dummysegment(pcb);
dummysegment.SetLayer( zone->GetLayer() );
dummysegment.m_Width = zone->m_ZoneMinThickness;
for( int ic = 1; ic <= imax; ic++ )
{
CPolyPt* endcorner = &zone->m_FilledPolysList[ic];
if( begincorner->utility == 0 ) // Draw only basic outlines, not extra segments
{
dummysegment.m_Start.x = begincorner->x;
dummysegment.m_Start.y = begincorner->y;
dummysegment.m_End.x = endcorner->x;
dummysegment.m_End.y = endcorner->y;
Draw3D_Track( &dummysegment );
}
if( (endcorner->end_contour) || (ic == imax) ) // the last corner of a filled area is found: draw it
{
if( endcorner->utility == 0 ) // Draw only basic outlines, not extra segments
{
dummysegment.m_Start.x = endcorner->x;
dummysegment.m_Start.y = endcorner->y;
dummysegment.m_End.x = firstcorner->x;
dummysegment.m_End.y = firstcorner->y;
Draw3D_Track( &dummysegment );
}
ic++;
if( ic < imax - 1 )
begincorner = firstcorner = &zone->m_FilledPolysList[ic];
}
else
begincorner = endcorner;
}
}
}
/* draw graphic items */
......@@ -434,12 +481,12 @@ void Pcb3D_GLCanvas::Draw3D_DrawText( TEXTE_PCB* text )
s_Text3DWidth = text->m_Width * g_Parm_3D_Visu.m_BoardScale;
glNormal3f( 0.0, 0.0, Get3DLayerSide( layer ) );
DrawGraphicText( NULL, NULL,
text->m_Pos, (EDA_Colors) color, text->m_Text,
text->m_Orient, text->m_Size,
text->m_HJustify,
text->m_VJustify,
text->m_Width, text->m_Italic,
Draw3dTextSegm );
text->m_Pos, (EDA_Colors) color, text->m_Text,
text->m_Orient, text->m_Size,
text->m_HJustify,
text->m_VJustify,
text->m_Width, text->m_Italic,
Draw3dTextSegm );
}
......@@ -478,8 +525,8 @@ void MODULE::Draw3D( Pcb3D_GLCanvas* glcanvas )
glPushMatrix();
glTranslatef( m_Pos.x * g_Parm_3D_Visu.m_BoardScale,
-m_Pos.y * g_Parm_3D_Visu.m_BoardScale,
g_Parm_3D_Visu.m_LayerZcoord[m_Layer] );
-m_Pos.y * g_Parm_3D_Visu.m_BoardScale,
g_Parm_3D_Visu.m_LayerZcoord[m_Layer] );
if( m_Orient )
{
......@@ -755,7 +802,7 @@ void D_PAD::Draw3D( Pcb3D_GLCanvas* glcanvas )
f_hole_coord[ii][0] = -hole * 0.707;
f_hole_coord[ii][1] = hole * 0.707;
RotatePoint( &f_hole_coord[ii][0], &f_hole_coord[ii][1],
angle - (ii * 450) );
angle - (ii * 450) );
f_hole_coord[ii][0] += drillx;
f_hole_coord[ii][1] += drilly;
}
......
......@@ -5,6 +5,14 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.
2009-feb-01 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++All:
change filename drawpanel_wxstruct.h to class_drawpanel.h
and move class BASE_SCREEN description from drawpanel_wxstruct.h to a new file: class_base_screen.h
minor enhancement for window zoom command.
refinements in 3D zones drawing.
2009-jan-31 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
++All:
......
......@@ -35,7 +35,6 @@ BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType )
m_Zoom = 32 * m_ZoomScalar;
m_Grid = wxSize( 50, 50 ); /* Default grid size */
m_UserGridIsON = FALSE;
m_Diviseur_Grille = 1;
m_Center = true;
m_CurrentSheetDesc = &g_Sheet_A4;
......@@ -118,6 +117,25 @@ wxPoint BASE_SCREEN::CursorRealPosition( const wxPoint& ScreenPos )
return curpos;
}
/** Function SetScalingFactor
* calculates the .m_Zoom member to have a given scaling facort
* @param the the current scale used to draw items on screen
* draw coordinates are user coordinates * GetScalingFactor( )
*/
void BASE_SCREEN::SetScalingFactor(double aScale )
{
int zoom = static_cast<int>( ceil(aScale * m_ZoomScalar) );
// Limit zoom to max and min allowed values:
if (zoom < m_ZoomList[0])
zoom = m_ZoomList[0];
int idxmax = m_ZoomList.GetCount() - 1;
if (zoom > m_ZoomList[idxmax])
zoom = m_ZoomList[idxmax];
SetZoom( zoom );
}
/**
* Calculate coordinate value for zooming.
*
......
......@@ -81,21 +81,18 @@ void WinEDA_DrawFrame::Window_Zoom( EDA_Rect& Rect )
* @param Rect = selected area to show after zooming
*/
{
int ii, jj;
int bestzoom;
double scalex, bestscale;
wxSize size;
/* Compute the best zoom */
Rect.Normalize();
size = DrawPanel->GetClientSize();
// Use ceil to at least show the full rect
ii = static_cast<int>( ceil(1.0 * Rect.GetSize().x / size.x) );
jj = static_cast<int>( ceil(1.0 * Rect.GetSize().y / size.y) );
bestzoom = MAX( ii, jj );
if( bestzoom <= 0 )
bestzoom = 1;
scalex = (double) Rect.GetSize().x / size.x;
bestscale = (double)Rect.GetSize().y / size.y;
bestscale = MAX( bestscale, scalex );
GetBaseScreen()->SetZoom( bestzoom * GetBaseScreen()->m_ZoomScalar );
GetBaseScreen()->SetScalingFactor( bestscale );
GetBaseScreen()->m_Curseur = Rect.Centre();
Recadre_Trace( TRUE );
}
......
......@@ -10,7 +10,7 @@
#endif
#include "base_struct.h"
#include "class_screen.h"
#include "class_sch_screen.h"
#include <wx/arrstr.h>
#include <wx/dynarray.h>
......
......@@ -15,7 +15,7 @@
#include "sch_item_struct.h"
#include "component_class.h"
#include "class_screen.h"
#include "class_sch_screen.h"
#include "class_drawsheet.h"
#include "class_drawsheetpath.h"
#include "class_text-label.h"
......
......@@ -9,7 +9,7 @@ COMMON_GLOBL wxString g_BuildVersion
# include "config.h"
(wxT(KICAD_SVN_VERSION))
# else
(wxT("(20090122-unstable)")) /* main program version */
(wxT("(20090201-unstable)")) /* main program version */
# endif
#endif
;
......@@ -20,7 +20,7 @@ COMMON_GLOBL wxString g_BuildAboutVersion
# include "config.h"
(wxT(KICAD_ABOUT_VERSION))
# else
(wxT("(20090122-unstable)")) /* svn date & rev (normally overridden) */
(wxT("(20090201-unstable)")) /* svn date & rev (normally overridden) */
# endif
#endif
;
......
/********************************************************/
/* drawpanel_wxstruct.h: */
/* descriptions des principales classes utilisees: */
/* ici classe: "WinEDA_DrawPanel", "BASE_SCREEN" */
/********************************************************/
/******************************
* drawpanel.h:
* define class WinEDA_DrawPanel
*************************************/
/* Doit etre inclus dans "wxstruch.h"
*/
......@@ -10,16 +9,9 @@
#ifndef PANEL_WXSTRUCT_H
#define PANEL_WXSTRUCT_H
#ifndef eda_global
#define eda_global extern
#endif
#include "colors.h"
class SCH_ITEM;
class BASE_SCREEN;
class Ki_PageDescr;
/* Simple class for handling grid arrays. */
class GRID_TYPE
......@@ -45,30 +37,30 @@ public:
WinEDA_DrawFrame* m_Parent;
EDA_Rect m_ClipBox; // the clipbox used in screen redraw (usually gives the visible area in internal units)
wxPoint m_CursorStartPos; // utile dans controles du mouvement curseur
int m_ScrollButt_unit; // Valeur de l'unite de scroll en pixels pour les boutons de scroll
int m_ScrollButt_unit; // Valeur de l'unite de scroll en pixels pour les boutons de scroll
bool m_AbortRequest; // Flag d'arret de commandes longues
bool m_AbortEnable; // TRUE si menu ou bouton Abort doit etre affiche
bool m_AbortRequest; // Flag d'arret de commandes longues
bool m_AbortEnable; // TRUE si menu ou bouton Abort doit etre affiche
bool m_AutoPAN_Enable; // TRUE to allow auto pan
bool m_AutoPAN_Request; // TRUE to request an auto pan (will be made only if m_AutoPAN_Enable = true)
bool m_AutoPAN_Enable; // TRUE to allow auto pan
bool m_AutoPAN_Request; // TRUE to request an auto pan (will be made only if m_AutoPAN_Enable = true)
int m_IgnoreMouseEvents; // when non-zero (true), then ignore mouse events
int m_IgnoreMouseEvents; // when non-zero (true), then ignore mouse events
bool m_Block_Enable; // TRUE to accept Block Commands
int m_CanStartBlock; // >= 0 (or >= n) if a block can start
bool m_PrintIsMirrored; // True when drawing in mirror mode. Used in draw arc function,
bool m_Block_Enable; // TRUE to accept Block Commands
int m_CanStartBlock; // >= 0 (or >= n) if a block can start
bool m_PrintIsMirrored; // True when drawing in mirror mode. Used in draw arc function,
// because arcs are oriented, and in mirror mode, orientations are reversed
// usefull to avoid false start block in certain cases (like switch from a sheet to an other scheet
int m_PanelDefaultCursor; // Current mouse cursor default shape id for this window
int m_PanelCursor; // Current mouse cursor shape id for this window
int m_CursorLevel; // Index for cursor redraw in XOR mode
int m_PanelDefaultCursor; // Current mouse cursor default shape id for this window
int m_PanelCursor; // Current mouse cursor shape id for this window
int m_CursorLevel; // Index for cursor redraw in XOR mode
/* Cursor management (used in editing functions) */
void (*ManageCurseur)( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); /* Fonction d'affichage sur deplacement souris
* si erase : effacement ancien affichage */
void (*ForceCloseManageCurseur)( WinEDA_DrawPanel* panel, wxDC* DC ); /* Fonction de fermeture forc�
* de la fonction ManageCurseur */
void (*ManageCurseur)( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); /* Fonction d'affichage sur deplacement souris
* si erase : effacement ancien affichage */
void (*ForceCloseManageCurseur)( WinEDA_DrawPanel* panel, wxDC* DC ); /* Fonction de fermeture forc�
* de la fonction ManageCurseur */
public:
......@@ -119,7 +111,7 @@ public:
/** Function CursorRealPosition
* @return the position in user units of location ScreenPos
* @param ScreenPos = the screen (in pixel) position co convert
*/
*/
wxPoint CursorRealPosition( const wxPoint& ScreenPos );
/** Function CursorScreenPosition
......@@ -170,272 +162,4 @@ public:
};
/**************************/
/* class DrawBlockStruct */
/**************************/
/* Definition d'un block pour les fonctions sur block (block move, ..) */
typedef enum { /* definition de l'etat du block */
STATE_NO_BLOCK, /* Block non initialise */
STATE_BLOCK_INIT, /* Block initialise: 1er point defini */
STATE_BLOCK_END, /* Block initialise: 2eme point defini */
STATE_BLOCK_MOVE, /* Block en deplacement */
STATE_BLOCK_STOP /* Block fixe (fin de deplacement) */
} BlockState;
/* codes des differentes commandes sur block: */
typedef enum {
BLOCK_IDLE,
BLOCK_MOVE,
BLOCK_COPY,
BLOCK_SAVE,
BLOCK_DELETE,
BLOCK_PASTE,
BLOCK_DRAG,
BLOCK_ROTATE,
BLOCK_INVERT,
BLOCK_ZOOM,
BLOCK_ABORT,
BLOCK_PRESELECT_MOVE,
BLOCK_SELECT_ITEMS_ONLY,
BLOCK_MIRROR_X,
BLOCK_MIRROR_Y
} CmdBlockType;
class DrawBlockStruct : public EDA_BaseStruct, public EDA_Rect
{
public:
BlockState m_State; /* Etat (enum BlockState) du block */
CmdBlockType m_Command; /* Type (enum CmdBlockType) d'operation */
EDA_BaseStruct* m_BlockDrawStruct; /* pointeur sur la structure
* selectionnee dans le bloc */
int m_Color; /* Block Color */
wxPoint m_MoveVector; /* Move distance in move, drag, copy ... command */
wxPoint m_BlockLastCursorPosition; /* Last Mouse position in block command
* = last cursor position in move commands
* = 0,0 in block paste */
public:
DrawBlockStruct();
~DrawBlockStruct();
void SetMessageBlock( WinEDA_DrawFrame* frame );
void Draw( WinEDA_DrawPanel* panel, wxDC* DC );
};
/*******************************************************************/
/* Class to handle how to draw a screen (a board, a schematic ...) */
/*******************************************************************/
class BASE_SCREEN : public EDA_BaseStruct
{
public:
wxPoint m_DrawOrg; /* offsets pour tracer le circuit sur l'ecran */
wxPoint m_Curseur; /* Screen cursor coordinate (on grid) in user units. */
wxPoint m_MousePosition; /* Mouse cursor coordinate (off grid) in user units. */
wxPoint m_MousePositionInPixels; /* Mouse cursor coordinate (off grid) in pixels. */
wxPoint m_O_Curseur; /* Relative Screen cursor coordinate (on grid) in user units.
* (coordinates from last reset position)*/
wxPoint m_ScrollbarPos; // Position effective des Curseurs de scroll
wxSize m_ScrollbarNumber; /* Valeur effective des Nombres de Scrool
* c.a.d taille en unites de scroll de la surface totale affichable */
wxPoint m_StartVisu; // Coord absolues du 1er pixel visualis�a l'ecran (en nombre de pixels)
wxSize m_SizeVisu; /* taille en pixels de l'ecran (fenetre de visu
* Utile pour recadrer les affichages lors de la
* navigation dans la hierarchie */
bool m_Center; /* fix the coordinate (0,0) position on screen : if TRUE (0,0) in centered on screen
* TRUE: when coordiantaes can be < 0 and > 0 all but schematic
* FALSE: when coordinates can be only >= 0 Schematic
*/
bool m_FirstRedraw;
/* Gestion des editions */
SCH_ITEM* EEDrawList; /* Object list (main data) for schematic */
EDA_BaseStruct* m_UndoList; /* Object list for the undo command (old data) */
EDA_BaseStruct* m_RedoList; /* Object list for the redo command (old data) */
int m_UndoRedoCountMax; /* undo/Redo command Max depth */
/* block control */
DrawBlockStruct BlockLocate; /* Bock description for block commands */
/* Page description */
Ki_PageDescr* m_CurrentSheetDesc;
int m_ScreenNumber;
int m_NumberOfScreen;
wxString m_FileName;
wxString m_Title; /* titre de la feuille */
wxString m_Date; /* date de mise a jour */
wxString m_Revision; /* code de revision */
wxString m_Company; /* nom du proprietaire */
wxString m_Commentaire1;
wxString m_Commentaire2;
wxString m_Commentaire3;
wxString m_Commentaire4;
private:
/* indicateurs divers */
char m_FlagRefreshReq; /* indique que l'ecran doit redessine */
char m_FlagModified; // indique modif du PCB,utilise pour eviter une sortie sans sauvegarde
char m_FlagSave; // indique sauvegarde auto faite
EDA_BaseStruct* m_CurrentItem; ///< Currently selected object
/* Valeurs du pas de grille et du zoom */
public:
wxSize m_Grid; /* Current grid. */
GridArray m_GridList;
bool m_UserGridIsON;
int m_Diviseur_Grille;
wxArrayInt m_ZoomList; /* Array of standard zoom coefficients. */
int m_Zoom; /* Current zoom coefficient. */
int m_ZoomScalar; /* Allow zooming to non-integer increments. */
public:
BASE_SCREEN( KICAD_T aType = SCREEN_STRUCT_TYPE );
~BASE_SCREEN();
BASE_SCREEN* Next() const { return (BASE_SCREEN*) Pnext; }
BASE_SCREEN* Back() const { return (BASE_SCREEN*) Pback; }
/**
* Function setCurItem
* sets the currently selected object, m_CurrentItem.
* @param current Any object derived from EDA_BaseStruct
*/
void SetCurItem( EDA_BaseStruct* current ) { m_CurrentItem = current; }
EDA_BaseStruct* GetCurItem() const { return m_CurrentItem; }
void InitDatas(); /* Inits completes des variables */
wxSize ReturnPageSize( void );
virtual int GetInternalUnits( void );
/** Function CursorRealPosition
* @return the position in user units of location ScreenPos
* @param ScreenPos = the screen (in pixel) position co convert
*/
wxPoint CursorRealPosition( const wxPoint& ScreenPos );
/* general Undo/Redo command control */
virtual void ClearUndoRedoList();
virtual void AddItemToUndoList( EDA_BaseStruct* item );
virtual void AddItemToRedoList( EDA_BaseStruct* item );
virtual EDA_BaseStruct* GetItemFromUndoList();
virtual EDA_BaseStruct* GetItemFromRedoList();
/* Manipulation des flags */
void SetRefreshReq() { m_FlagRefreshReq = 1; }
void ClrRefreshReq() { m_FlagRefreshReq = 0; }
void SetModify() { m_FlagModified = 1; m_FlagSave = 0; }
void ClrModify() { m_FlagModified = 0; m_FlagSave = 1; }
void SetSave() { m_FlagSave = 1; }
void ClrSave() { m_FlagSave = 0; }
int IsModify() { return m_FlagModified & 1; }
int IsRefreshReq() { return m_FlagRefreshReq & 1; }
int IsSave() { return m_FlagSave & 1; }
//----<zoom stuff>----------------------------------------------------------
/** Function GetScalingFactor
* @return the the current scale used to draw items on screen
* draw coordinates are user coordinates * GetScalingFactor( )
*/
double GetScalingFactor( )
{
return (double) m_ZoomScalar / GetZoom();
}
/** Function SetScalingFactor
* @param the the current scale used to draw items on screen
* draw coordinates are user coordinates * GetScalingFactor( )
*/
void SetScalingFactor(double aScale )
{
SetZoom( (int) round(aScale * m_ZoomScalar) );
}
/** Function GetZoom
* @return the current zoom factor
* Note: the zoom factor is NOT the scaling factor
* the scaling factor is m_ZoomScalar * GetZoom()
*/
int GetZoom() const;
/**
* Function SetZoom
* adjusts the current zoom factor
*/
void SetZoom( int coeff );
/**
* Function SetZoomList
* sets the list of zoom factors.
* @param aZoomList An array of zoom factors in ascending order, zero terminated
*/
void SetZoomList( const wxArrayInt& zoomlist );
int Scale( int coord );
void Scale( wxPoint& pt );
void Scale( wxSize& sz );
int Unscale( int coord );
void Unscale( wxPoint& pt );
void Unscale( wxSize& sz );
void SetNextZoom(); /* ajuste le prochain coeff de zoom */
void SetPreviousZoom(); /* ajuste le precedent coeff de zoom */
void SetFirstZoom(); /* ajuste le coeff de zoom a 1*/
void SetLastZoom(); /* ajuste le coeff de zoom au max */
//----<grid stuff>----------------------------------------------------------
wxSize GetGrid(); /* retourne la grille */
void SetGrid( const wxSize& size );
void SetGrid( int );
void SetGridList( GridArray& sizelist );
void AddGrid( const GRID_TYPE& grid );
void AddGrid( const wxSize& size, int id );
void AddGrid( const wxRealPoint& size, int units, int id );
/**
* Function RefPos
* returns the reference position, coming from either the mouse position or the
* the cursor position.
* @param useMouse If true, return mouse position, else cursor's.
* @return wxPoint - The reference point, either the mouse position or
* the cursor position.
*/
wxPoint RefPos( bool useMouse )
{
return useMouse ? m_MousePosition : m_Curseur;
}
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
virtual wxString GetClass() const
{
return wxT( "BASE_SCREEN" );
}
#if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void Show( int nestLevel, std::ostream& os );
#endif
};
#endif /* #ifndef PANEL_WXSTRUCT_H */
......@@ -22,11 +22,12 @@
#include "base_struct.h"
#include "appl_wxstruct.h"
#include "drawpanel_wxstruct.h"
#include "class_drawpanel.h"
#include "class_base_screen.h"
//C++ guarantees that operator delete checks its argument for null-ness
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) delete (p); (p) = NULL; //C++ guarantees that operator delete checks its argument for null-ness
#define SAFE_DELETE(p) delete (p); (p) = NULL;
#endif
#define INTERNAL_UNIT_TYPE 0 // Internal unit = inch
......
No preview for this file type
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -178,7 +178,6 @@ bool Read_Config( const wxString& project_name )
if( ScreenPcb )
{
ScreenPcb->m_Diviseur_Grille = Pcbdiv_grille;
ScreenPcb->AddGrid( g_UserGrid, g_UserGrid_Unit, ID_POPUP_GRID_USER );
}
......@@ -220,8 +219,6 @@ void WinEDA_PcbFrame::Update_config( wxWindow* displayframe )
if( FullFileName.IsEmpty() )
return;
Pcbdiv_grille = GetScreen()->m_Diviseur_Grille;
/* ecriture de la configuration */
wxGetApp().WriteProjectConfig( FullFileName, wxT( "/pcbnew" ),
ParamCfgList );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment