chicken_dy/Assets/WX-WASM-SDK/UnityMarkdownViewer/Editor/Scripts/MarkdownViewer.cs

237 lines
7.7 KiB
C#
Executable File

using Markdig;
using UnityEditor;
using UnityEngine;
using Markdig.Extensions.JiraLinks;
namespace WeChatWASM.MDV
{
public class MarkdownViewer
{
private GUISkin mSkin = null;
private string mText = string.Empty;
private string mCurrentPath = string.Empty;
private HandlerImages mHandlerImages = new HandlerImages();
private HandlerNavigate mHandlerNavigate = new HandlerNavigate();
private Vector2 mScrollPos = Vector2.zero;
private Layout mLayout = null;
private bool mRaw = false;
private static History mHistory = new History();
public MarkdownViewer( GUISkin skin, string path, string content )
{
mSkin = skin;
mCurrentPath = path;
mText = content;
mHistory.OnOpen( mCurrentPath );
mLayout = ParseDocument();
mHandlerImages.CurrentPath = mCurrentPath;
mHandlerNavigate.CurrentPath = mCurrentPath;
mHandlerNavigate.History = mHistory;
mHandlerNavigate.FindBlock = ( id ) => mLayout.Find( id );
mHandlerNavigate.ScrollTo = ( pos ) => mScrollPos.y = pos;
}
//------------------------------------------------------------------------------
public bool Update()
{
return mHandlerImages.Update();
}
//------------------------------------------------------------------------------
Layout ParseDocument()
{
var context = new Context( mSkin, mHandlerImages, mHandlerNavigate );
var builder = new LayoutBuilder( context );
var renderer = new RendererMarkdown( builder );
var pipelineBuilder = new MarkdownPipelineBuilder()
.UseAutoLinks()
;
if( !string.IsNullOrEmpty( Preferences.JIRA ) )
{
pipelineBuilder.UseJiraLinks( new JiraLinkOptions( Preferences.JIRA ) );
}
var pipeline = pipelineBuilder.Build();
pipeline.Setup( renderer );
var doc = Markdown.Parse( mText, pipeline );
renderer.Render( doc );
return builder.GetLayout();
}
//------------------------------------------------------------------------------
#if !UNITY_2018
private float mHeight = 1.0f;
#endif
protected Rect GetEditorRect()
{
#if !UNITY_2018
// fix for Screen.height
var offset = 450.0f;
var scale = 2.0f;
// calculate working space
if( Event.current.type == EventType.Layout )
{
mHeight = ( Screen.height - offset ) / scale;
}
// reserve space (we are going to paint on it directly)
GUILayout.Space( mHeight );
// return working rect
return new Rect( 0.0f, 10.0f, EditorGUIUtility.currentViewWidth, mHeight );
#else
GUILayout.FlexibleSpace();
var rectContainer = GUILayoutUtility.GetLastRect();
rectContainer.width = EditorGUIUtility.currentViewWidth;
return rectContainer;
#endif
}
//------------------------------------------------------------------------------
public void Draw()
{
GUI.skin = mSkin;
GUI.enabled = true;
// content rect
var rectContainer = GetEditorRect();
// clear background
var rectFullScreen = new Rect( 0.0f, rectContainer.yMin - 4.0f, Screen.width, Screen.height );
GUI.DrawTexture( rectFullScreen, GUI.skin.window.normal.background, ScaleMode.StretchToFill, false );
// scroll window
var padLeft = 8.0f;
var padRight = 4.0f;
var padHoriz = padLeft + padRight;
var scrollWidth = GUI.skin.verticalScrollbar.fixedWidth;
var minWidth = rectContainer.width - scrollWidth - padHoriz;
var maxHeight = ContentHeight( minWidth );
var hasScrollbar = maxHeight >= rectContainer.height;
var contentWidth = hasScrollbar ? minWidth : rectContainer.width - padHoriz;
var rectContent = new Rect( -padLeft, 0.0f, contentWidth, maxHeight );
// draw content
using( var scroll = new GUI.ScrollViewScope( rectContainer, mScrollPos, rectContent ) )
{
mScrollPos = scroll.scrollPosition;
if( mRaw )
{
rectContent.width = minWidth - GUI.skin.button.fixedWidth;
DrawRaw( rectContent );
}
else
{
DrawMarkdown( rectContent );
}
}
DrawToolbar( rectContainer, hasScrollbar ? scrollWidth + padRight : padRight );
}
//------------------------------------------------------------------------------
float ContentHeight( float width )
{
return mRaw ? GUI.skin.GetStyle( "raw" ).CalcHeight( new GUIContent( mText ), width ) : mLayout.Height;
}
//------------------------------------------------------------------------------
void DrawToolbar( Rect rect, float marginRight )
{
var style = GUI.skin.button;
var size = style.fixedHeight;
var btn = new Rect( rect.xMax - size - marginRight, rect.yMin, size, size );
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( mRaw ? "btnRaw" : "btnFile" ) ) )
{
mRaw = !mRaw;
}
if( mRaw == false )
{
if( mHistory.CanForward )
{
btn.x -= size;
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnForward" ) ) )
{
Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Forward() );
}
}
if( mHistory.CanBack )
{
btn.x -= size;
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnBack" ) ) )
{
Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Back() );
}
}
}
}
//------------------------------------------------------------------------------
void DrawRaw( Rect rect )
{
EditorGUI.SelectableLabel( rect, mText, GUI.skin.GetStyle( "raw" ) );
}
//------------------------------------------------------------------------------
void DrawMarkdown( Rect rect )
{
switch( Event.current.type )
{
case EventType.Ignore:
break;
case EventType.ContextClick:
var menu = new GenericMenu();
menu.AddItem( new GUIContent( "View Source" ), false, () => mRaw = !mRaw );
menu.ShowAsContext();
break;
case EventType.Layout:
mLayout.Arrange( rect.width );
break;
default:
mLayout.Draw();
break;
}
}
}
}